当我在已经销毁的Activity上调用finish()时会发生什么?

时间:2015-04-09 15:32:47

标签: android android-activity android-volley android-lifecycle

我在查看现有的一些活动代码时意识到,某些Volley异步网络响应处理程序调用{​​{1}}返回调用者(通常通过finish()启动我的Activity)。像这样:

startActivityForResult

在最近对一个bug进行调查之后,我意识到我的代码没有正确处理旋转情况 - 我理论上可以在活动实例A1的销毁和活动实例A2的创建之间调用网络响应处理程序当设备旋转时。调用A1的private Response.Listener<MyResponse> mResponseListener = new Response.Listener<MyResponse>(){ @Override public void onResponse(MyResponse myResponse) { // I could get here *after* rotation was initiated // do stuff finish(); }; } 之后调用finish()会产生什么影响? “我们已经完成”的事实是否已经失去了? A2是否会被创建并坚持使用,好像从未调用onDestroy

2 个答案:

答案 0 :(得分:3)

  

在调用A1的onDestroy之后调用finish()有什么影响?

我不确定,但对我来说,它似乎应该完成活动并将其从任务的后台堆栈中删除。

我认为问题的根源在于其他地方 - 活动和碎片确实不适合处理网络或其他异步操作。您应该将活动和碎片更像是哑巴根据MVC或MVP设计的视图 - 他们应该接受来自控制器的一些数据并相应地渲染他们的视图。

因此,制作异步请求的适当位置类似于普通Java类,其实例保存在Application上下文中,而不是保存在任何Activity上下文中。这样,执行异步操作的对象就不会绑定到变幻无常的Activity / Fragment生命周期。

例如,我喜欢使用EventBus及其跨线程粘性事件来在发出请求的对象和必须显示结果的Activity之间进行通信,在Activity {{1}中订阅一个事件监听器} onResume中的回调和取消订阅。

一篇帮助我学习思考活动和片段的文章是this one by Matt Swanson

答案 1 :(得分:1)

我相信onDestroy之后发生的事情是Activity活动到达其生命周期的末尾并且很快被垃圾收集。

我可以为您的案例考虑两种解决方案

  1. 取消onDestroy中的所有排球请求。您可以使用RequestQueue#cancelAll取消给定特定标签的所有请求。在实例化Volley请求时附加此标记。

  2. 使用由Otto或EventBus提供的Publisher-Subsriber模式。我只是展示奥托的魔力。

  3. public static class ResponseEvent{
       MyResponse myResponse;
       public ResponseEvent(MyResponse myResponse){
          this.myResponse = myResponse;
       }
    }
    
    public void onCreate(){
       BusProvider.getInstance().register(this);// register this activity as subscriber  
    }
    
    public void onDestroy(){
       BusProvider.getInstance().unregister(this);
    }    
    // it is up you where you want to register and unregister depending
    // whether you want to digest the response when the activity 
    // is on foreground or background as well. 
    
    
    
    private Response.Listener<MyResponse> mResponseListener = new Response.Listener<MyResponse>(){
    @Override public void onResponse(MyResponse myResponse) {
    
        // I could get here *after* rotation was initiated
    
        // do stuff
    
       BusProvider.getInstance().post(new ResponseEvent(myResponse)); 
    //sends this event to previously registered subcsriber. 
    //The subscriber method will be active as long the activity 
    //hasn't been de-registered. 
    //Nothing will happen after unregister has been called.  
    
    }};
    
    //this is the subscriber method that will digest your response
    @Subsribe
    public void onGotResponse(ResponseEvent event){
       // do your stuff with response here. 
     finish(); 
    // notice I moved finish() here so you can be sure 
    // it will only be called as long as the activity is still active
    }