聽起來是個很有用的東西,但可惜的是它隱藏的問題其實也不少,其中一個就是它很容易造成 memroy leak
通常使用 AsyncTask 時,都會用 non-static inner class 來使用,因為這樣可以很方便的引用 outer class 裡面的欄位,例如下面一個簡單的例子
但是,當你用 non-static inner class 來使用 AsyncTask 的時候,你就有可能造成 memroy leak,因為 non-static inner class 會隱式的持有對 outer 的 reference,例如在這個例子中 MyAsyncTask 就會持有 MainActivity 的 reference,若是在 longRunningProcess 函式操作途中 MainActivity 被銷毀的話,MainActivity 會因為被 MyAsyncTask 持有 reference 而無法被 GC 回收,造成 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 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);
- }
- }
- }
那我們要怎樣避免 AsyncTask memory leak,就是
memory leak 只是 AsyncTask 的一個常見的坑之一,網路上找一找會發現它的坑還有很多,限制也不少,Android 本意是要提供一個好用方便的 class,讓開發者不用煩惱 background thread 跟 UI thread 交互作用的問題,專注於開發業務邏輯,但現在反而開發者要注意更多 AsyncTask 的坑與細節,看起來也並沒有減少多少開發者的工作量
- 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);
- }
- }
- }
沒有留言:
張貼留言