Trying to detect ActionMode memory leak










6















I have been trying to find the source of ActionMode memory leak for days now without luck. I have an activity with several fragments and when I leave the fragment having ActionMode (while auto cancelling it), LeakCanary detects a memory leak.



I have nulled both ActionMode and ActionMode.Callback on destroy() and even tried doing it on onDestroyActionMode().



Here is my LeakCanary screenshot:



https://i.imgur.com/RUbdqj3.png



I hope someone points me in the right direction.



P.S. I have suspected it has something to do with ActionMode.Callback. Though, I could not find any methods for the CallBack that destroys it. I start the ActionMode using startSupportActionMode(mActionModeCallback). I have tried to find a method to remove the mActionModeCallback from that, too, but no methods.



Here is my full ActionMode code:



private ActionMode mActionMode;
private ActionMode.Callback mActionModeCallback;

public void startCAB()

if (mActionMode == null)
mActionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);



private void buildActionModeCallBack()

mActionModeCallback = new ActionMode.Callback()
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_cab, menu);
return true;


@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
return false;


@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
switch (item.getItemId())
... Some Code ...



@Override
public void onDestroyActionMode(ActionMode mode)
mActionMode = null;
mActionModeCallback = null; // Tried with and without this.

;


public void finishActionMode()

mActionMode.finish();


@Override
public void onDestroy()

super.onDestroy();
mActionMode = null;
mActionModeCallback = null;



Parent Activity containing fragments:



@Override
public void onTabUnselected(TabLayout.Tab tab)

clearCAB();


private void clearCAB()

int index = mPagerAdapter.getCurrentFragmentIndex();
FragmentOne fragmentOne = (FragmentOne) mPagerAdapter.instantiateItem(mViewPager, index);
fragmentOne.finishActionMode();










share|improve this question
























  • Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

    – earthw0rmjim
    Nov 12 '18 at 12:47











  • Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

    – Jack
    Nov 12 '18 at 13:03











  • Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

    – mliu
    Nov 25 '18 at 10:34















6















I have been trying to find the source of ActionMode memory leak for days now without luck. I have an activity with several fragments and when I leave the fragment having ActionMode (while auto cancelling it), LeakCanary detects a memory leak.



I have nulled both ActionMode and ActionMode.Callback on destroy() and even tried doing it on onDestroyActionMode().



Here is my LeakCanary screenshot:



https://i.imgur.com/RUbdqj3.png



I hope someone points me in the right direction.



P.S. I have suspected it has something to do with ActionMode.Callback. Though, I could not find any methods for the CallBack that destroys it. I start the ActionMode using startSupportActionMode(mActionModeCallback). I have tried to find a method to remove the mActionModeCallback from that, too, but no methods.



Here is my full ActionMode code:



private ActionMode mActionMode;
private ActionMode.Callback mActionModeCallback;

public void startCAB()

if (mActionMode == null)
mActionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);



private void buildActionModeCallBack()

mActionModeCallback = new ActionMode.Callback()
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_cab, menu);
return true;


@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
return false;


@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
switch (item.getItemId())
... Some Code ...



@Override
public void onDestroyActionMode(ActionMode mode)
mActionMode = null;
mActionModeCallback = null; // Tried with and without this.

;


public void finishActionMode()

mActionMode.finish();


@Override
public void onDestroy()

super.onDestroy();
mActionMode = null;
mActionModeCallback = null;



Parent Activity containing fragments:



@Override
public void onTabUnselected(TabLayout.Tab tab)

clearCAB();


private void clearCAB()

int index = mPagerAdapter.getCurrentFragmentIndex();
FragmentOne fragmentOne = (FragmentOne) mPagerAdapter.instantiateItem(mViewPager, index);
fragmentOne.finishActionMode();










share|improve this question
























  • Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

    – earthw0rmjim
    Nov 12 '18 at 12:47











  • Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

    – Jack
    Nov 12 '18 at 13:03











  • Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

    – mliu
    Nov 25 '18 at 10:34













6












6








6


1






I have been trying to find the source of ActionMode memory leak for days now without luck. I have an activity with several fragments and when I leave the fragment having ActionMode (while auto cancelling it), LeakCanary detects a memory leak.



I have nulled both ActionMode and ActionMode.Callback on destroy() and even tried doing it on onDestroyActionMode().



Here is my LeakCanary screenshot:



https://i.imgur.com/RUbdqj3.png



I hope someone points me in the right direction.



P.S. I have suspected it has something to do with ActionMode.Callback. Though, I could not find any methods for the CallBack that destroys it. I start the ActionMode using startSupportActionMode(mActionModeCallback). I have tried to find a method to remove the mActionModeCallback from that, too, but no methods.



Here is my full ActionMode code:



private ActionMode mActionMode;
private ActionMode.Callback mActionModeCallback;

public void startCAB()

if (mActionMode == null)
mActionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);



private void buildActionModeCallBack()

mActionModeCallback = new ActionMode.Callback()
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_cab, menu);
return true;


@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
return false;


@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
switch (item.getItemId())
... Some Code ...



@Override
public void onDestroyActionMode(ActionMode mode)
mActionMode = null;
mActionModeCallback = null; // Tried with and without this.

;


public void finishActionMode()

mActionMode.finish();


@Override
public void onDestroy()

super.onDestroy();
mActionMode = null;
mActionModeCallback = null;



Parent Activity containing fragments:



@Override
public void onTabUnselected(TabLayout.Tab tab)

clearCAB();


private void clearCAB()

int index = mPagerAdapter.getCurrentFragmentIndex();
FragmentOne fragmentOne = (FragmentOne) mPagerAdapter.instantiateItem(mViewPager, index);
fragmentOne.finishActionMode();










share|improve this question
















I have been trying to find the source of ActionMode memory leak for days now without luck. I have an activity with several fragments and when I leave the fragment having ActionMode (while auto cancelling it), LeakCanary detects a memory leak.



I have nulled both ActionMode and ActionMode.Callback on destroy() and even tried doing it on onDestroyActionMode().



Here is my LeakCanary screenshot:



https://i.imgur.com/RUbdqj3.png



I hope someone points me in the right direction.



P.S. I have suspected it has something to do with ActionMode.Callback. Though, I could not find any methods for the CallBack that destroys it. I start the ActionMode using startSupportActionMode(mActionModeCallback). I have tried to find a method to remove the mActionModeCallback from that, too, but no methods.



Here is my full ActionMode code:



private ActionMode mActionMode;
private ActionMode.Callback mActionModeCallback;

public void startCAB()

if (mActionMode == null)
mActionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);



private void buildActionModeCallBack()

mActionModeCallback = new ActionMode.Callback()
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_cab, menu);
return true;


@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
return false;


@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
switch (item.getItemId())
... Some Code ...



@Override
public void onDestroyActionMode(ActionMode mode)
mActionMode = null;
mActionModeCallback = null; // Tried with and without this.

;


public void finishActionMode()

mActionMode.finish();


@Override
public void onDestroy()

super.onDestroy();
mActionMode = null;
mActionModeCallback = null;



Parent Activity containing fragments:



@Override
public void onTabUnselected(TabLayout.Tab tab)

clearCAB();


private void clearCAB()

int index = mPagerAdapter.getCurrentFragmentIndex();
FragmentOne fragmentOne = (FragmentOne) mPagerAdapter.instantiateItem(mViewPager, index);
fragmentOne.finishActionMode();







java android






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 13:02







Jack

















asked Nov 12 '18 at 12:05









JackJack

637




637












  • Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

    – earthw0rmjim
    Nov 12 '18 at 12:47











  • Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

    – Jack
    Nov 12 '18 at 13:03











  • Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

    – mliu
    Nov 25 '18 at 10:34

















  • Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

    – earthw0rmjim
    Nov 12 '18 at 12:47











  • Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

    – Jack
    Nov 12 '18 at 13:03











  • Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

    – mliu
    Nov 25 '18 at 10:34
















Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

– earthw0rmjim
Nov 12 '18 at 12:47





Have you tried calling mActionMode.finish() instead of setting the reference explicitly to null?

– earthw0rmjim
Nov 12 '18 at 12:47













Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

– Jack
Nov 12 '18 at 13:03





Yes, I have added the code from my parent activity, that shows where I finish the CAB on swipe.

– Jack
Nov 12 '18 at 13:03













Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

– mliu
Nov 25 '18 at 10:34





Hitting the same issue in my app, which uses a listview inside a fragment, hosted in a view pager.

– mliu
Nov 25 '18 at 10:34












2 Answers
2






active

oldest

votes


















0














It seems the ActionMode in the activity has a reference to the fragment's layout which is causing the memory leak and preventing the fragment from getting GC'ed. I couldn't find a way to remove the reference.



In my use case, I'm using a ListView inside the fragment that was activating the activity's ActionMode (via listener.setMultiChoiceModeListener).



My hacky solution: In the fragment's onDestroyView, remove the listView (or whichever view activated the ActionMode) from the layout and remove all listeners for the list view. I made a kotlin extension method for it:



fun ListView.removeViewAndClearListeners() 
setMultiChoiceModeListener(null)
setOnScrollListener(null)
onItemClickListener = null

(parent as? ViewGroup)?.removeView(this)



After doing this, the leak is gone.






share|improve this answer






























    -1














    I am still wondering why you are relying on ActionMode.Callback. I had an application where I was supposed to create a Custom Menu on long press and I wasted almost 2 months on this issue :



    ActionModeCallback does not work



    I am not sure If you are aware of this or not, The ActionMode Callback barely works on all devices. After a lot of research, I came to know that devices who are focusing too much on battery consumption and optimization will not let your background services and some callbacks work as expected.



    Try testing your code on MI or Oppo/Vivo devices. It will jump directly to onDestroyActionMode instead of calling onActionItemClicked






    share|improve this answer






















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53261839%2ftrying-to-detect-actionmode-memory-leak%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      It seems the ActionMode in the activity has a reference to the fragment's layout which is causing the memory leak and preventing the fragment from getting GC'ed. I couldn't find a way to remove the reference.



      In my use case, I'm using a ListView inside the fragment that was activating the activity's ActionMode (via listener.setMultiChoiceModeListener).



      My hacky solution: In the fragment's onDestroyView, remove the listView (or whichever view activated the ActionMode) from the layout and remove all listeners for the list view. I made a kotlin extension method for it:



      fun ListView.removeViewAndClearListeners() 
      setMultiChoiceModeListener(null)
      setOnScrollListener(null)
      onItemClickListener = null

      (parent as? ViewGroup)?.removeView(this)



      After doing this, the leak is gone.






      share|improve this answer



























        0














        It seems the ActionMode in the activity has a reference to the fragment's layout which is causing the memory leak and preventing the fragment from getting GC'ed. I couldn't find a way to remove the reference.



        In my use case, I'm using a ListView inside the fragment that was activating the activity's ActionMode (via listener.setMultiChoiceModeListener).



        My hacky solution: In the fragment's onDestroyView, remove the listView (or whichever view activated the ActionMode) from the layout and remove all listeners for the list view. I made a kotlin extension method for it:



        fun ListView.removeViewAndClearListeners() 
        setMultiChoiceModeListener(null)
        setOnScrollListener(null)
        onItemClickListener = null

        (parent as? ViewGroup)?.removeView(this)



        After doing this, the leak is gone.






        share|improve this answer

























          0












          0








          0







          It seems the ActionMode in the activity has a reference to the fragment's layout which is causing the memory leak and preventing the fragment from getting GC'ed. I couldn't find a way to remove the reference.



          In my use case, I'm using a ListView inside the fragment that was activating the activity's ActionMode (via listener.setMultiChoiceModeListener).



          My hacky solution: In the fragment's onDestroyView, remove the listView (or whichever view activated the ActionMode) from the layout and remove all listeners for the list view. I made a kotlin extension method for it:



          fun ListView.removeViewAndClearListeners() 
          setMultiChoiceModeListener(null)
          setOnScrollListener(null)
          onItemClickListener = null

          (parent as? ViewGroup)?.removeView(this)



          After doing this, the leak is gone.






          share|improve this answer













          It seems the ActionMode in the activity has a reference to the fragment's layout which is causing the memory leak and preventing the fragment from getting GC'ed. I couldn't find a way to remove the reference.



          In my use case, I'm using a ListView inside the fragment that was activating the activity's ActionMode (via listener.setMultiChoiceModeListener).



          My hacky solution: In the fragment's onDestroyView, remove the listView (or whichever view activated the ActionMode) from the layout and remove all listeners for the list view. I made a kotlin extension method for it:



          fun ListView.removeViewAndClearListeners() 
          setMultiChoiceModeListener(null)
          setOnScrollListener(null)
          onItemClickListener = null

          (parent as? ViewGroup)?.removeView(this)



          After doing this, the leak is gone.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 25 '18 at 10:59









          mliumliu

          817813




          817813























              -1














              I am still wondering why you are relying on ActionMode.Callback. I had an application where I was supposed to create a Custom Menu on long press and I wasted almost 2 months on this issue :



              ActionModeCallback does not work



              I am not sure If you are aware of this or not, The ActionMode Callback barely works on all devices. After a lot of research, I came to know that devices who are focusing too much on battery consumption and optimization will not let your background services and some callbacks work as expected.



              Try testing your code on MI or Oppo/Vivo devices. It will jump directly to onDestroyActionMode instead of calling onActionItemClicked






              share|improve this answer



























                -1














                I am still wondering why you are relying on ActionMode.Callback. I had an application where I was supposed to create a Custom Menu on long press and I wasted almost 2 months on this issue :



                ActionModeCallback does not work



                I am not sure If you are aware of this or not, The ActionMode Callback barely works on all devices. After a lot of research, I came to know that devices who are focusing too much on battery consumption and optimization will not let your background services and some callbacks work as expected.



                Try testing your code on MI or Oppo/Vivo devices. It will jump directly to onDestroyActionMode instead of calling onActionItemClicked






                share|improve this answer

























                  -1












                  -1








                  -1







                  I am still wondering why you are relying on ActionMode.Callback. I had an application where I was supposed to create a Custom Menu on long press and I wasted almost 2 months on this issue :



                  ActionModeCallback does not work



                  I am not sure If you are aware of this or not, The ActionMode Callback barely works on all devices. After a lot of research, I came to know that devices who are focusing too much on battery consumption and optimization will not let your background services and some callbacks work as expected.



                  Try testing your code on MI or Oppo/Vivo devices. It will jump directly to onDestroyActionMode instead of calling onActionItemClicked






                  share|improve this answer













                  I am still wondering why you are relying on ActionMode.Callback. I had an application where I was supposed to create a Custom Menu on long press and I wasted almost 2 months on this issue :



                  ActionModeCallback does not work



                  I am not sure If you are aware of this or not, The ActionMode Callback barely works on all devices. After a lot of research, I came to know that devices who are focusing too much on battery consumption and optimization will not let your background services and some callbacks work as expected.



                  Try testing your code on MI or Oppo/Vivo devices. It will jump directly to onDestroyActionMode instead of calling onActionItemClicked







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 27 '18 at 4:30









                  Nir PatelNir Patel

                  159112




                  159112



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53261839%2ftrying-to-detect-actionmode-memory-leak%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

                      Syphilis

                      Darth Vader #20