Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
264 views
in Technique[技术] by (71.8m points)

android - view.getViewTreeObserver().addOnGlobalLayoutListener leaks Fragment

When I use the GlobalLayoutListener to see if the softKeyboard is opened or not the fragment is not garbageCollected anymore after it is destroyed.

What I do:

  • I remove the Listener in the onDestroy() of my Fragment
  • I set the Listener to null in onDestroy()
  • I set the view that is observed to null in onDestroy()

Still leaks the fragment.

Does anyone had a similar issue and knows a fix for it??

My 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();
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I believe strongly removing the Listener, referenced by a View object, in onDestroy() is too late. This override method occurs after onDestroyView(), which supposed to "...clean up resources associated with its View." You may use the same code in onStop() instead. Although I did not use this technique.

I can suggest this code, which I have used without any issues with the debugger.

// 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);
        }
    }
});

Notes:

  • Since getViewTreeObserver is used for layouts, normally you need this listener for a short time only. Hence the listener is removed immediately.
  • The second call to removeOnGlobalLayoutListener() should be crossed out by the Studio since it is not available before JELLY_BEAN.
  • Pragma code @SuppressWarnings("deprecation") is not necessary if you're using Android Studio.
  • Code myView = rootView.findViewById(R.id.myView); may need to change to a more applicable code to your app or situation.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...