聽起來是個很有用的東西,但可惜的是它隱藏的問題其實也不少,其中一個就是它很容易造成 memroy leak
通常使用 AsyncTask 時,都會用 non-static inner class 來使用,因為這樣可以很方便的引用 outer class 裡面的欄位,例如下面一個簡單的例子
public class MainActivity extends Activity { private Object mMyObject; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // Somewhere the AsyncTask is started public class MyAsyncTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { // Do work longRunningProcess(); return result; } @Override protected void onPostExecute(String result) { Log.d("Object: " + mMyObject.toString()); Log.d("MyAsyncTask", "Received result: " + result); } } }但是,當你用 non-static inner class 來使用 AsyncTask 的時候,你就有可能造成 memroy leak,因為 non-static inner class 會隱式的持有對 outer 的 reference,例如在這個例子中 MyAsyncTask 就會持有 MainActivity 的 reference,若是在 longRunningProcess 函式操作途中 MainActivity 被銷毀的話,MainActivity 會因為被 MyAsyncTask 持有 reference 而無法被 GC 回收,造成 memory leak
那我們要怎樣避免 AsyncTask memory leak,就是
public class MainActivity extends Activity { private Object mMyObject; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // Somewhere the AsyncTask is started public static class MyAsyncTask extends AsyncTask<Void, Void, String> { private WeakReference<MainActivity> mActivity; public MyAsyncTask(MainActivity activity) { mActivity = new WeakReference<>(activity); } @Override protected String doInBackground(Void... params) { // Do work longRunningProcess(); return result; } @Override protected void onPostExecute(String result) { MainActivity activity = mActivity.get(); if (activity == null || activity.isFinishing()) return; Log.d("Object: " + mMyObject.toString()); Log.d("MyAsyncTask", "Received result: " + result); } } }memory leak 只是 AsyncTask 的一個常見的坑之一,網路上找一找會發現它的坑還有很多,限制也不少,Android 本意是要提供一個好用方便的 class,讓開發者不用煩惱 background thread 跟 UI thread 交互作用的問題,專注於開發業務邏輯,但現在反而開發者要注意更多 AsyncTask 的坑與細節,看起來也並沒有減少多少開發者的工作量
沒有留言:
張貼留言