Android AsyncTask 取消全部任務 , 解決記憶體洩漏問題
阿新 • • 發佈:2018-12-21
以下程式碼具備的功能:
1. 取消當前新增的所有 AsyncTask , 儘量減少重複的網路請求任務
(場景: 我們需要在一個介面中定時每 10s 請求一次網路獲取一次資料 ,我們知道網路請求時間是不固定的 ,可能很快的請求完成,也可能很慢,因此,我為了儘量節省開銷,希望每次都能在指定的時間執行一次網路請求就好了) |
2. 嘗試解決記憶體洩漏問題
(記憶體洩漏,多是由於有些介面或物件銷燬或生命週期結束後,仍然有一些引用持有該介面或物件 ,如: 想在一個已經銷燬的介面中進行更新UI操作, 記憶體洩漏帶來的影響: 隨著洩漏的累積,app將消耗完記憶體) |
3. 迴圈請求網路
實現定時請求網路的功能 |
程式碼開始 ---->>>
Activity 部分:
public class MainActivity extends AppCompatActivity{ private static final String TAG = "MainActivity"; private List<String> showData = new ArrayList<>(); private ImRunnable mImRunnable; Handler mHandler = new Handler(); private MainAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); mImRunnable = new ImRunnable(); mHandler.removeCallbacks(mImRunnable);//清除上一次任務的影響 mHandler.postDelayed(mImRunnable, 300);//延時請求網路 } private void initView() { RecyclerView rcv = (RecyclerView) findViewById(R.id.rcv); rcv.setLayoutManager(new GridLayoutManager(this, 4)); mAdapter = new MainAdapter(showData); rcv.setAdapter(mAdapter); } //執行延時任務 private class ImRunnable implements Runnable, OnResponseCallback { @Override public void run() { Log.i("NotifyService", "run: " + Thread.currentThread()); HashMap<String, String> parameters = new HashMap<>(); parameters.put("key", "value"); NetUtils netUtils = new NetUtils(MainActivity.this,this); NetUtils.putTaskFloor(netUtils);//todo 儲存每次建立的 AsyncTask 物件(弱引用),在取消全部的時候會用到 netUtils.execute(new TestWeb(parameters)); //重複執行本身 mHandler.postDelayed(this, 300); } @Override public void onSuccess(List<String> stringList) { Log.i(TAG, "onSuccess: "); if (stringList.get(0).equals("pass")) { stringList.remove(0); showData.clear(); showData.addAll(stringList); mAdapter.setData(showData); mAdapter.notifyDataSetChanged(); Toast.makeText(MainActivity.this, "更新了資料!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "資料讀取失敗", Toast.LENGTH_SHORT).show(); } } @Override public void onFail() { Log.i(TAG, "onFail: "); } } @Override protected void onDestroy() { super.onDestroy(); showData.clear(); showData = null; mHandler.removeCallbacks(mImRunnable); NetUtils.isNeedLoading = false; NetUtils.cancelAllRunningTask(); int size = NetUtils.allTask.size(); Log.i(TAG, "onDestroy: 退出後還有多少: "+size); System.gc(); } }
AsyncTask 部分:
public class NetUtils extends AsyncTask<BaseRequest, Void, List<String>> { public static List<WeakReference<NetUtils>> allTask = new ArrayList<>(); private WeakReference<Activity> weakAty; private final OnResponseCallback mOnResponseCallback; public static boolean isNeedLoading = true; public static boolean isNeedSingleTask = true;//是否需要每次只允許一個任務執行 public NetUtils(Activity activity, OnResponseCallback onResponseCallback) { this.mOnResponseCallback = onResponseCallback; weakAty = new WeakReference<Activity>(activity); } public static void putTaskFloor(NetUtils netUtils) { allTask.add(new WeakReference<NetUtils>(netUtils)); } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected List<String> doInBackground(BaseRequest... voids) { if (!isNeedLoading) { return null; } if (isCancelled()) { return null; } try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } Log.e("NetUtils", "doInBackground:"); return null; } @Override protected void onPostExecute(List<String> stringList) { super.onPostExecute(stringList); isNeedLoading = true; if (isNeedSingleTask) { cancelAllRunningTask();//todo 拿到結果後,將再等待中的任務全部取消 } Activity mActivity; Activity activity = mActivity = (Activity) weakAty.get(); if (activity != null && !activity.isFinishing()) { //activity != null && !activity.isFinishing() 決定了是否繼續讓持有的 activity 做事 //即只有噹噹前的 activity 沒有 finish 的時候我們才有必要去更新UI if (stringList != null) { if (stringList.get(0).equals("pass")) { if (mOnResponseCallback != null) { mOnResponseCallback.onSuccess(stringList); } } else { if (mOnResponseCallback != null) { mOnResponseCallback.onFail(); } } } else { if (mOnResponseCallback != null) { mOnResponseCallback.onFail(); } } } Log.e("NetUtils", "onPostExecute: 正在執行 AsyncTask from NetUtils"); } public static void cancelAllRunningTask() { if (allTask != null && allTask.size() > 0) { for (int i = 0; i < allTask.size(); i++) { NetUtils netUtils = allTask.get(i).get(); if (!netUtils.isCancelled()) { netUtils.cancel(true);//沒有取消就取消 Log.w("NetUtils", "cancelAll: 正在執行 AsyncTask from NetUtils"); allTask.remove(i); } else { allTask.remove(i); } int size = NetUtils.allTask.size(); Log.i("NetUtils", "cancelAllRunningTask: 取消一個任務後還有多少: "+size); } } } }
public interface OnResponseCallback {
void onSuccess(List<String> stringList);
void onFail();
}
結束: 如果有更好的寫法,請不吝賜教 [握手]