3

I have one custom textview which has five city names and spannable click listener for each one of them. Code is as follow

/**
 * Created by @raj on 26/04/18.
 */
class TopCitiesTextView : TextView {

    private  var mListener: OnCityClickListener? = null

    constructor(ctx: Context?) : super(ctx) {
        initView(ctx, null, 0)
    }

    constructor(ctx: Context?, attrs: AttributeSet?) : super(ctx, attrs) {
        initView(ctx, attrs, 0)
    }

    constructor(ctx: Context?, attrs: AttributeSet?, defStyle: Int) : super(ctx, attrs, defStyle) {
        initView(ctx, attrs, defStyle)
    }

    private fun initView(ctx: Context?, attrs: AttributeSet?, defStyle: Int) {
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        val cityArray: Array<out String> = context.resources.getStringArray(R.array.top_cities_view_text)
        val spannableString: SpannableString = SpannableString(cityArray[0])
        this.text = spannableString
        this.append(" ")
        for (i in 1 until cityArray.size) {
            val citySpannableString = SpannableString(cityArray[i])
            citySpannableString.setSpan(object : ClickableSpan() {
                override fun onClick(widget: View?) {
                        mListener?.onCityClicked(cityArray[i])
                }
                override fun updateDrawState(ds: TextPaint) {
                    super.updateDrawState(ds)
                    ds.isUnderlineText = false
                }

            }, 0, citySpannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            this.append(citySpannableString)
            if (i != cityArray.size-1)
                this.append(", ")
        }
        movementMethod = LinkMovementMethod.getInstance()
    }

    fun setCityClickListener(listener: OnCityClickListener) {
        this.mListener = listener
    }

    interface OnCityClickListener {
        fun onCityClicked(city: String?)
    }
}

But the issue is that I am getting memory leak while using this textview in fragment's layout(xml) file.

Here is the screenshot of leakcanary.

enter image description here

How to remove this memory leak?

Raj Suvariya
  • 1,592
  • 3
  • 14
  • 36

1 Answers1

2

Remove the ClickableSpan from text in onDestroy of your Activity to avoid the Leak.

    if (textView.getText() instanceof SpannableString) {
          SpannableString spannableStr = (SpannableString) textView.getText();
          ClickableSpan[] spans = spannableStr.getSpans(0, spannableStr.length(), ClickableSpan.class);
          for (ClickableSpan span : spans) {
             spannableStr.removeSpan(span);
          }
          textView.setText(spannableStr);
    }
Krishna
  • 462
  • 1
  • 5
  • 6
  • 6
    Tried this. But it's still leaking. – sagar suri Aug 22 '19 at 07:36
  • 2
    not sure it's the right clue, but usually when you setup spans, you also setup movementMethod, e.g: ``` textView.movementMethod = LinkMovementMethod.getInstance() ``` maybe setting movementMethod to null would help? – Lukas Jun 15 '22 at 14:16