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.
How to remove this memory leak?
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);
}