Activity release 资源的正确姿势

谈一谈在Activity 中释放资源

最近的项目中,出现了一个很有意思的bug, 具体的细节如下:

在 Activity A 中,跳转到 Activity B,存在一个单例对象,在Activity 的 onCreate()进行初始化,然后在 onDestroy()里面进行重置,具体的调用代码如下:

Activity A:

public class ViewStubLayoutParamsActivity extends Activity{
      @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         .....
         initView();
        SingleTone.getInstance().setRoomId(10);
    }
   @Override
   protected void onDestroy() {
        super.onDestroy();
        SingleTone.getInstance().clear();
   }
  private void initView(){
     findViewById(R.id.tv_viewstub).setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
       Intent intent = new Intent(ViewStubLayoutParamsActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }
        });
  }

}

代码很简单,就是点击一个按钮,然后跳转另一个 Activity。另一个 Activity 的代码如下:

public class MainActivity extends AppCompatActivity {
        @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SingleTone.getInstance().setRoomId(11);
    }
      @Override
    protected void onDestroy() {
        super.onDestroy();
        SingleTone.getInstance().clear();
    }
}

但是实际上的结果是,我在 Activity B 里面拿到的值,是被重置后的值,也就是 clear()方法重置后的值;这里的原因是Activity 生命周期的问题,这个场景中,Activity 的生命周期调用方法如下:

所以,在 Activity B onCreate()执行之后, Activity A 的 onDestroy()才执行,导致单例对象被重置。

那么我们有没有办法避免这个问题?答案是可以的。我们可以在 finish()方法里面去释放资源,

public void finish() {
    finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}

Activity A 的 finish()方法,会在 onDestroy() 之前调用,并且会在 Activity B 的onCreate() 之前调用,这样就达到了重置数据的目的。

释放资源

考虑以下几种场景:

  1. Activity 是栈顶 Activity,由于回退被销毁,则所有资源需要释放,可以在 OnDestroy()里面释放。
  2. Activity 由于切换被压入 Activity 栈,失去栈顶位置,并且没有调用 finish()方法。由于 Activity 只会经历 onPause()和onStop()这两个方法都不适合做大量的操作,否则会阻塞新的 Activity 启动。
  3. 同样是场景二,但是调用了 finish()方法,这时,如果是单例类的资源,可以在 finish()方法释放,如果是View 相关资源,数据库资源等最好在 OnDstory()方法里面释放。

原理解析

刚刚说的施放资源的时机,需要你掌握Activty 启动相关的知识。这里做一些简单的分析(基于 API 25 ):Activity A 启动 Activty B 的时候,调用 startActivity()方法,其执行步骤大致如下:

  1. Activity A 发送进程间消息到 ActivityManagerService,告诉AMS 要启动 Activity B

  2. AMS 会将需要启动的 Activity B 的信息保存下来,然后发送信息告知 Activity A 进行中止操作。

  3. Activity A 收到中止信息,进行中止操作,并且通知 AMS 自己已经中止了。

  4. AMS 将保存下来的 Activity B 的信息,发送给 Activity A 和 B(假设它们是同一个进程)所在的进程,从而在对应的进程执行 Activity B 的启动操作。

后序如果 Activity A 调用了 finish()方法,其 onDestroy()方法才会被调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值