Android TextView未删除的ChangeWatchers导致内存泄漏
我们有活动和片段泄漏,并已将原因追溯到TextView上未删除的ChangeWatchers 情景: 活动A启动活动B。B在其布局中有一个文本密码编辑文本字段。活动B结束 HPROF转储显示活动B仍有一个实例。其gcroot路径如下所示:Android TextView未删除的ChangeWatchers导致内存泄漏,android,Android,我们有活动和片段泄漏,并已将原因追溯到TextView上未删除的ChangeWatchers 情景: 活动A启动活动B。B在其布局中有一个文本密码编辑文本字段。活动B结束 HPROF转储显示活动B仍有一个实例。其gcroot路径如下所示: test.maa.LoginActivity '- mContext android.widget.EditText '- this$0 android.widget.TextView$ChangeWatcher '- [1] java.
test.maa.LoginActivity
'- mContext android.widget.EditText
'- this$0 android.widget.TextView$ChangeWatcher
'- [1] java.lang.Object[13]
'- mSpans android.text.SpannableStringBuilder
'- mSource android.text.method.PasswordTransformationMethod$PasswordCharSequence
'- mText android.text.MeasuredText
'- mMeasured android.text.StaticLayout
'- sStaticLayout class android.text.DynamicLayout
如果将Linkify.addLinks链接到文本视图,也会发生这种情况
有没有办法清理活动B?据我所知,这似乎是Android中与TextView ChangeWatcher和Linkify或Html.fromHtml可扩展字符串相关的一个bug。通过在活动的onDestroy()中调用
setText(null)
,我可以解决这个问题。可能还有其他解决方法也可以,但我无法找到有关泄漏的任何进一步信息。尝试在onCreateView()中使用应用程序上下文,而不是活动上下文来处理此特定视图(其中包含任何安卓:textIsSelectable=“true”组件)
对我们来说,问题是由
EditText
中的PasswordTransformationMethod
引起的。特别是对我们来说,它被包装在一个TextInputLayout
中,因此我们必须像这样在那里切换它(此代码在片段中#onDestroyView()
):
发生在androidx.appcompat:appcompat:1.0.0你说“活动B完成”-它是如何“完成”的?您是在显式调用
finish()
、按下后退按钮还是其他方法?test.maa.LoginActivity是B?您是否在转储HPROF之前强制执行GC,以确保它还没有被收集?或者只是暂停了一下,仍然引用了see@MisterSquonkqFurther在不同设备上的测试显示,此问题发生在运行3.1的GSlate上,但在运行2.3.4B的Thunderbolt上没有发生。通过调用finish(),我在我们的应用程序上看到了相同的问题。我尝试过,几天来似乎找不到任何解决方法。也可以看到我的帖子
// Singleton
class MyApplication extends Application {
private static MyApplication mApp;
@Override
public void onCreate() {
mApp = this;
}
public static MyApplication getApp() {
return mApp;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Suggested inflater use Activity Context
// So we must tu use Application Context
Context context = MyApplication.getApp().getApplicationContext();
LayoutInflater myLayoutInflater = LayoutInflater.from(context);
View view = myLayoutInflater.inflate(R.layout.my_view, container, false);
return view;
}
TextInputLayout passwordTextInputLayout = root.findViewById(R.id.textInputLayout);
if (passwordTextInputLayout.isPasswordVisibilityToggleEnabled())
passwordTextInputLayout.setPasswordVisibilityToggleEnabled(false);