Search code examples
androidmemoryout-of-memoryactivity-finishonbackpressed

finish() leaking memory but onBackPressed() is not


I was attempting to track down memory leaks today in an application which has been hitting out-of-memory on some of the older devices. One of the leaks I found really threw me. I solved the leak but I was wondering if anybody had any insight into why the fix works at all.

The activity (let's call it activity B) that is leaking has an icon that is an 'x' for the user to exit that activity. When the x is pressed, it called finish() and then returns to activity A. The code for this click event is below:

    View ivExit = findViewById(R.id.imageview_exit);
    ivExit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!isFinishing()) {
                finish();
            }
        }
    });

The result is that it would work as expected but was leaking memory. However, with one simple change I was able to run the same exact test without any leak. All I had to do was change finish() to onBackPressed() and it no longer leaked. This is very strange to me because I was under the impression that onBackPressed() and finish() are essentially the same thing, and yet one of them leaks memory and the other does not. Does anybody know why this would be the case?


Solution

  • The difference is that in FragmentedActivity (that is the parent of AppCompatActivity) has following code in onBackPressed:

    public void onBackPressed() {
        if (!mFragments.popBackStackImmediate()) {
            finish();
        }
    }
    

    And it hasn't any specific implementation forfinish(). So looks like this popBackStackImmediate somehow affects your flow. I found OS 5.1.1 implementation :

     @Override
     public boolean popBackStackImmediate() {
         checkStateLoss();
         executePendingTransactions();
         return popBackStackState(mActivity.mHandler, null, -1, 0);
     }
    

    executePendingTransactions() could be the reason why behavior is different between onBackPressed() and finish() calls.