2012-04-25 122 views
1

在模拟器(ADT v17.0.0)或设备(原始Droid)中进行方向更改时,我注意到该活动将经历多个创建 - 破坏循环有时。我发现这个blog post提到的问题,但没有提供解决方案。我的应用程序(API 8)当前在onPause中保存用户数据,并在onCreate/onStart中检索该数据,该数据在单次重新启动时可以正常工作,但是如果循环中出现并发问题背靠背。特别是如果在保存完成之前开始加载,则“最后机会”数据将丢失。Android - 多重活动重新启动时的并发问题

我读过更快的屏幕方向更改Android开发人员文章,其中提到通过onRetainNonConfigurationInstance/getLastNonConfigurationInstance传输对象。我尝试使用onRetain/getLast ...就像一个标志,告诉活动是否“重新启动”,这是可行的,但我仍然有一个主要问题,不知道是否/何时现有的保存/加载操作完成。

并发&线程管理不是我的最强的西装,所以我在寻找,做至少一个保存在任意数量的后端到回重新启动的&负载,没有内存泄漏的解决方案。由于快速创建 - 破坏循环可能因非定向原因而发生,因此仅涉及打破/处理定向变化的想法实际上并不是我所追求的。

Here's a log file摘录了一些周期,您可以看到活动的创建位置 - 从横向到纵向两次销毁。这里是什么,我现在得到的摘录:

onPause() { 
    file_manager.saveTemporaryPattern(); // writes to OutputStream on UI thread 
} 

onStart() { 
    findViewById (R.id.main_screen).post (new Runnable() { 
     file_manager.loadTemporaryPattern(); // reads from InputStream on UI thread 
    }); 

    if (getLastNonConfigurationInstance() != null) { 
     // DO SOMETHING HERE? 
    } 
} 

onRetainNonConfigurationInstance() { 
    return dummy_object; 
} 

回答

1

管理人发送的负荷,解决问题并发/保存调用处理程序线程连接到应用程序上下文,而不是活动场景。必须在调用中设置Load vs Save标记以检查Save-> Load-> Save模式,从而避免在横向 - >纵向方向更改上获取不完整活动生命周期的奇怪行为。

它在测试设备上的开发&中工作,并且不会泄漏活动上下文,因此我们将看到它是如何发挥作用的。

在YourApp延伸应用:

private Handler fileAccessThread = null; 

public void onCreate() { 
    super.onCreate(); 

    if (fileAccessThread == null) { 
     fileAccessThread = new Handler(); 
     token = 0; 
    } 
} 

public void postCallbackFileAccess (int _token, Runnable _callback) { 
    switch (_token) { 
    case TOKEN_SAVE: 
     // Save must follow load, not another save 
     if (token == TOKEN_SAVE) { return; } 
     token = _token; 
     break; 

    case TOKEN_LOAD: 
//  Have to allow load->load, otherwise data gets lost/deleted 
//  if (token == TOKEN_LOAD) { return; } 
     token = _token; 
     break; 
    } 

    fileAccessThread.post (_callback); 
} 

在YourActivity:

protected void onStart() { 
    super.onStart(); 

    ((YourApp) getApplication()).postCallbackFileAccess (
     YourApp.TOKEN_LOAD, new Runnable() { 
      @Override 
      public void run() { 
       file_manager.load(); 
      } 
    }); 
} 

protected void onPause() { 
    super.onPause(); 

    ((YourApp) getApplication()).postCallbackFileAccess (
     YourApp.TOKEN_SAVE, new Runnable() { 
      @Override 
      public void run() { 
       file_manager.save(); 
      } 
    }); 
}