我在查看现有的一些活动代码时意识到,某些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
?
答案 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活动到达其生命周期的末尾并且很快被垃圾收集。
我可以为您的案例考虑两种解决方案
取消onDestroy中的所有排球请求。您可以使用RequestQueue#cancelAll取消给定特定标签的所有请求。在实例化Volley请求时附加此标记。
使用由Otto或EventBus提供的Publisher-Subsriber模式。我只是展示奥托的魔力。
的
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
}