[英]How can I tell if my context is still valid?
我現在正在處理一個相當普遍的情況 - 通過網絡下載一些數據,然后更新視圖以顯示它。 顯然,我想在后台進行網絡下載,然后在主 UI 線程上更新視圖。 現在查看我的代碼,我有點擔心我的 Activity 及其 UI 元素在我更新它們之前被殺死。 這是我想到的本質:
Thread update = new Thread() {
public void run() {
final Data newData = requestData();
if (newData != null) {
post(new Runnable() {
public void run() {
Toast.makeText(MyClass.this, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show();
}
});
}
}
};
update.start();
似乎有可能在我下載數據時,活動可能會被破壞。 那會發生什么? 我的線程會繼續執行嗎? 我最終會嘗試訪問死對象嗎?
通常我通過 AsycTask 來做這件事,但這次的工作似乎很簡單,只需內聯線程啟動線程的東西。 我會通過使用 AsyncTask 使事情變得更好嗎?
如果您的Context
是一個Activity
,您可以使用isFinishing()
方法檢查它是否正在完成或已完成:
if ( context instanceof Activity ) {
Activity activity = (Activity)context;
if ( activity.isFinishing() ) {
return;
}
}
Toast.makeText(context, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show();
您真正想要使用的是AsyncTaskLoader 。 這些是我在 Android API 中最喜歡的新類。 我一直在使用它們,它們就是為了解決這樣的問題。 您不必擔心何時停止下載或類似的事情。 所有線程邏輯都會為您處理,包括告訴線程在活動已關閉時停止。 只需在loadInBackground()方法中說出您想做什么。 請注意,如果您正在為低於 3.0 的 API 進行開發,您仍然可以通過Android 支持包訪問所有加載器。
如果您使用匿名類,它們將具有對外部類的內部引用,因此它不會因為其他引用已被清除而突然變得不可訪問。 AsyncTask
實際上不會改變任何東西,它使用類似的機制來通知結果。
您可以使用loader ,它們旨在與活動生命周期同步。 它們僅在 Android 3.0 之后可用,但您可以使用支持包在任何 1.6 或更高版本的設備上使用它們。
還有一個更簡單的解決方案,您可以只使用一個布爾字段來指示活動是否已經消失。 你應該在onPause()
設置這個字段(或者當你認為你不再需要通知時)並在你顯示 toast 時檢查它。 您甚至不必使用同步,因為該字段僅限於主線程,因此絕對安全。 順便說一句,如果您在onDestroy()
以外的其他地方更改此字段,請不要忘記添加一條語句,將您的字段重置回對應方法。
public class MyActivity extends Activity {
private boolean activityDestroyed = false;
@Override
protected void onDestroy() {
activityDestroyed = true;
}
private void updateData() {
new Thread() {
@Override
public void run() {
final Data newData = requestData();
if (newData == null) return;
runOnUiThread(new Runnable() {
public void run() {
if (activityDestroyed) return;
Toast.makeText(MyActivity.this, "Blah",
Toast.LENGTH_SHORT).show();
}
});
}
}.start();
}
}
我通常使用Weak Reference
來避免在視圖中泄漏上下文
上下文的弱引用
private var mContext: WeakReference<Context?>? = null
分配上下文
mContext = WeakReference(appContext)
獲取上下文
mContext .get()
驗證上下文
if (mContext?.get() is Activity &&
(mContext?.get() as Activity).isFinishing){
return
}
庫蒂斯是對的。 但是,如果你真的想保持簡單,你可以試試這個:
class MyActivity extends Activity {
static MyActivity context;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
MyActivity.context = this;
}
@Override
public void onDestroy() {
super.onDestroy();
MyActivity.context = null;
}
}
然后你只需在你的類中使用MyActivity.context
(並在那里檢查 null )。 如果您希望在您的應用程序處於后台時甚至不顯示 Toast,請改用 onPause/onResume。
同樣,這是快速而懶惰的方法。 AsyncTask 或 AsyncTaskLoader 是您應該如何做事。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.