Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 对已销毁的活动调用finish()时会发生什么情况?_Android_Android Activity_Android Volley_Android Lifecycle - Fatal编程技术网

Android 对已销毁的活动调用finish()时会发生什么情况?

Android 对已销毁的活动调用finish()时会发生什么情况?,android,android-activity,android-volley,android-lifecycle,Android,Android Activity,Android Volley,Android Lifecycle,在查看一些现有的活动代码时,我意识到一些截取异步网络响应处理程序调用finish()返回给调用者(调用者通常通过startActivityForResult启动我的活动)。大概是这样的: private Response.Listener<MyResponse> mResponseListener = new Response.Listener<MyResponse>(){ @Override public void onResponse(MyResponse m

在查看一些现有的活动代码时,我意识到一些截取异步网络响应处理程序调用
finish()
返回给调用者(调用者通常通过
startActivityForResult
启动我的活动)。大概是这样的:

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();
    };
}
private Response.Listener mResponseListener=new Response.Listener(){
@覆盖公共void onResponse(MyResponse MyResponse){
//我可以在轮换开始后到这里
//做事
完成();
};
}
在最近对一个bug进行了一些调查之后,我意识到我的代码没有正确处理旋转情况——理论上,当设备旋转时,网络响应处理程序可以在活动实例A1的销毁和活动实例A2的创建之间调用。调用A1的
onDestroy
后调用
finish()
有什么影响?“我们完蛋了”这一事实是真的吗?A2是否会被创建并像从未调用过
finish
一样一直保持

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

我不确定,但在我看来,它应该完成活动并将其从任务的后堆栈中移除

我认为你的问题的根源在别处,尽管-活动和片段确实不是处理网络或其他异步操作的合适位置。在MVC或MVP设计中,您应该更像对待哑视图一样对待活动和片段-它们应该接受来自控制器的一些数据,并相应地呈现它们的视图

因此,发出异步请求的合适位置应该是一个普通Java类,其实例保存在
应用程序
上下文中,而不是任何
活动
上下文中。这样,执行异步操作的对象就不会绑定到易变的活动/片段生命周期

例如,我喜欢使用带有跨线程粘性事件的
EventBus
在发出请求的对象和必须显示结果的活动之间进行通信,在活动的
onResume
回调中订阅事件侦听器,并在
onPause
中取消订阅

这篇文章极大地帮助我学会思考活动和片段

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

我不确定,但在我看来,它应该完成活动并将其从任务的后堆栈中移除

我认为你的问题的根源在别处,尽管-活动和片段确实不是处理网络或其他异步操作的合适位置。在MVC或MVP设计中,您应该更像对待哑视图一样对待活动和片段-它们应该接受来自控制器的一些数据,并相应地呈现它们的视图

因此,发出异步请求的合适位置应该是一个普通Java类,其实例保存在
应用程序
上下文中,而不是任何
活动
上下文中。这样,执行异步操作的对象就不会绑定到易变的活动/片段生命周期

例如,我喜欢使用带有跨线程粘性事件的
EventBus
在发出请求的对象和必须显示结果的活动之间进行通信,在活动的
onResume
回调中订阅事件侦听器,并在
onPause
中取消订阅


一篇对我学习思考活动和片段有很大帮助的文章是。

我相信onDestroy之后发生的事情是,活动已经到了生命周期的尽头,很快就会被垃圾收集

我可以为你的案子想出两个解决办法

  • 取消onDestroy中的所有截击请求。您可以使用RequestQueue#cancelAll来取消给定特定标记的所有请求。此标记在实例化截击请求时附加

  • 使用发布者订阅模式,如Otto或EventBus提供的模式。我来演示一下奥托的魔力

  • 公共静态类ResponseEvent{
    我的反应我的反应;
    公共响应事件(MyResponse MyResponse){
    this.myResponse=myResponse;
    }
    }
    public void onCreate(){
    BusProvider.getInstance().register(this);//将此活动注册为订阅服务器
    }
    公共空间{
    BusProvider.getInstance().unregister(此);
    }    
    //注册和注销的位置取决于您自己
    //当活动启动时,是否要消化响应
    //也在前景或背景上。
    private Response.Listener mResponseListener=new Response.Listener(){
    @覆盖公共void onResponse(MyResponse MyResponse){
    //我可以在轮换开始后到这里
    //做事
    BusProvider.getInstance().post(新响应事件(myResponse));
    //将此事件发送到以前注册的子服务器。
    //订阅服务器方法将一直处于活动状态
    //还没有注销。
    //调用unregister后不会发生任何事情。
    }};
    //这是将消化您的响应的订户方法
    @改编
    公共无效事件响应(响应事件){
    //在这里用回应做你的事情。
    完成();
    //请注意,我将finish()移到了这里,以便您可以确定
    //只有在活动仍处于活动状态时才会调用它
    }
    
    我相信onDestroy之后发生的事情是,该活动到达其生命周期的末尾,很快就会被垃圾回收

    我可以为你的案子想出两个解决办法

  • 取消onDestroy中的所有截击请求。您可以使用RequestQueue#cancelAll来取消给定特定标记的所有请求。此标记在实例化截击请求时附加

  • 使用Publisher-S
    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
    }