当我使用GlobalLayoutListener
查看softKeyboard是否被打开时,片段在被销毁后不再是garbageCollected。
我的所作所为:
onDestroy()
中的监听器null
onDestroy()
onDestroy()
仍在泄漏碎片。
有没有人遇到过类似的问题并知道修复它?
我的onDestroy
:
@Override
public void onDestroy(){
Log.d(TAG , "onDestroy");
if(Build.VERSION.SDK_INT < 16){
view.getViewTreeObserver().removeGlobalOnLayoutListener(gLayoutListener);
}else{
view.getViewTreeObserver().removeOnGlobalLayoutListener(gLayoutListener);
}
view = null;
gLayoutListener = null;
super.onDestroy();
}
答案 0 :(得分:28)
我认为在onDestroy
()中强烈删除View对象引用的Listener为时已晚。这种覆盖方法发生在onDestroyView
()之后,它应该&#34; ...清理与其View相关的资源。&#34;
您可以在onStop()
中使用相同的代码。虽然我没有使用这种技术。
我可以建议使用这个代码,我使用它而没有调试器的任何问题。
// Code below is an example. Please change it to code that is more applicable to your app.
final View myView = rootView.findViewById(R.id.myView);
myView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressLint("NewApi") @SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
// Obtain layout data from view...
int w = myView.getWidth();
int h = myView.getHeight();
// ...etc.
// Once data has been obtained, this listener is no longer needed, so remove it...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
myView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
else {
myView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
注意:
getViewTreeObserver
用于布局,通常只需短时间内就可以使用此监听器。因此,立即删除了听众。removeOnGlobalLayoutListener
()的第二次调用应由Studio划掉,因为它在JELLY_BEAN之前不可用。@SuppressWarnings("deprecation")
。myView = rootView.findViewById(R.id.myView);
可能需要更改为适用于您的应用或情况的更适用的代码。答案 1 :(得分:1)
我有同样的问题,但我通过删除onDestroy()中的侦听器来解决它。请注意在JellyBean周围更改使用的方法。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}
@Override
public void onDestroy() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mView.getViewTreeObserver().removeGlobalOnLayoutListener(mGlobalLayoutListener);
} else {
mView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
}
super.onDestroy();
}
答案 2 :(得分:1)
嗯,也许这有点矫枉过正,但如果没有消息来源就很难说清楚,所以试试吧。让你的gLayoutListener
成为一个静态的内部类(不要强烈引用你的片段)。
如果您需要在侦听器内使用片段或其字段执行某些操作,请在自定义侦听器类的构造函数内创建WeakReference<YourFragment>
,并通过此引用访问您的片段。不要忘记检查weakref.get() != null
。
答案 3 :(得分:0)
您可以尝试创建自定义布局,并将其作为根视图放在xml中,而不是使用它。
class CustomLayout extends LinearLayout{
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
然后覆盖onsizechanged方法
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (h < oldh) {
// there is a difference, means keyboard is open.
} else {
}
}
我假设您的应用程序仅支持一种模式(纵向或横向)
<强>更新强>:
在
中做所有事情@Override
public void onDestroyView(){
super.onDestroyView();
}
因为我认为您正在onCreateView()
中初始化侦听器,所以应该在onDestoryView()
中删除侦听器。只有在片段被销毁时才会调用onDestroy(),而不是在状态更改期间调用。
答案 4 :(得分:0)
我也在自定义视图中遇到此问题。我在自定义视图构造函数中的子视图上注册了onPreDrawListener
,并在onDetachedFromWindow
中取消注册了它。内存泄漏持续存在。为了解决这个问题,我尝试了所有方法,但最后我必须编写一个不基于TreeObserver的替代机制。