2012-04-25 85 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(); 
      } 
    }); 
}