首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android AsyncTask 非靜態內部類別存取外部類別 Context:解決 No enclosing instance 錯誤

     編輯:程式設計綜合問答

錯誤原因

非靜態內部類別 MyCustomTask extends AsyncTask 隱含持有外部類別實例參考。若在靜態上下文(如 static 方法)建立實例,會拋出 No enclosing instance。

解決方案

1. 將 AsyncTask 設為 static 內部類別,透過建構子傳遞 Context

public class MyActivity extends AppCompatActivity {
    // 靜態內部類別,不持有外部實例參考
    private static class MyCustomTask extends AsyncTask<Void, Void, Long> {
        private final WeakReference<Context> contextRef; // 弱參考防洩漏

        MyCustomTask(Context context) {
            this.contextRef = new WeakReference<>(context);
        }

        @Override
        protected Long doInBackground(Void... params) {
            // 背景工作
            return 0L;
        }

        @Override
        protected void onPostExecute(Long result) {
            Context context = contextRef.get();
            if (context != null) {
                Toast.makeText(context, "完成", Toast.LENGTH_LONG).show();
            }
        }
    }

    // 使用
    new MyCustomTask(this).execute();
}

2. 或將 AsyncTask 移至獨立頂層類別檔案

// MyCustomTask.java
public class MyCustomTask extends AsyncTask<Void, Void, Long> {
    private final WeakReference<Context> contextRef;
    public MyCustomTask(Context context) { this.contextRef = new WeakReference<>(context); }
    // ... 同上
}

3. 現代替代:Kotlin Coroutine / RxJava / LiveData


// Coroutine 在 Activity/ViewModel 中
lifecycleScope.launch(Dispatchers.IO) {
    val result = repository.fetchData()
    withContext(Dispatchers.Main) {
        toast("完成")
        uiState.value = result
    }
}

關鍵原則

  • AsyncTask 內部類別**必須宣告為 static**,或提取為獨立類別。
  • Context 使用 WeakReference 避免記憶體洩漏(Activity 銷毀時可被 GC 回收)。
  • 新專案**棄用 AsyncTask**,改用協程或 Flow。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved