完整方案:命令模式+非同步執行+取消機制,非同步機制
引子
- 隨著項目的發展,activity的代碼變得越來越龐雜,不易維護。這便出現了諸如MVP等模式來分層實現以達到給activity減負的效果,從而降低商務邏輯的耦合,提高可維護性。本文從另外一個角度出發,利用命令模式來實現給activity瘦身的目標。採用本文的方案,同樣可以將商務邏輯抽離,並於後台執行,同時提供了不錯的取消機制。
介面
- iCmd介面,主要api是exe方法,傳回值是bundle對象;其他mTag,mCanceled用於取消相關
public abstract class iCmd { private boolean mCanceled = false; private Object mTag; public void cancel() { mCanceled = true; } public boolean isCanceled() { return mCanceled; } public Object getTag() { return mTag; } public iCmd setTag(Object tag) { mTag = tag; return this; } public abstract Bundle exe() throws Exception;}
- iCmdListener 命令監聽介面,onPreExecute負責命令開始的通知;onPostExecute負責命令結束的通知並帶回返回結果
public interface iCmdListener { public void onPreExecute();// public void onProgressUpdate(int progress); public void onPostExecute(Bundle resultBundle);}
- iCmdExecutor命令執行器,下列代碼僅列出主要api,具體的實現文後的github地址
public class iCmdExecutor {//用於取消和具體tag相關的cmd public static void cancelAll(final Object tag)//非同步執行該命令,並在主線程執行回調通知 public static void exeAsync(final iCmd cmd, final iCmdListener listener, Object tag)//同步執行該命令,並在當前線程執行回調通知 public static void exeSync(iCmd cmd, iCmdListener listener, Object tag)}
用法
public class CmdAdd extends iCmd { private static final String TAG = "test"; private BigInteger a; private BigInteger b; public CmdAdd(BigInteger a, BigInteger b) { this.a = a; this.b = b; } @Override public Bundle exe() throws InterruptedException { Log.i(TAG, this + ", exe, tid=" + Thread.currentThread().getId()); Thread.sleep(5000);// demo for long operation Bundle bundle = new Bundle(); bundle.putString("result", a.add(b).toString()); return bundle; }}
iCmdExecutor.exeAsync(new CmdAdd(new BigInteger("123"), new BigInteger( "12345678901234567890123456789012345678901234567890")), new iCmdListener() { @Override public void onPreExecute() { Log.e(TAG, "onPreExecute, tid=" + Thread.currentThread().getId()); } @Override public void onPostExecute(Bundle resultBundle) { Log.e(TAG, "onPostExecute, tid=" + Thread.currentThread().getId() + ", resultBundle=" + resultBundle); if (null != resultBundle) { String res = resultBundle.getString("result"); tvAddResult.setText(res); } } }, this);
iCmdExecutor.cancelAll(this);
連結
- https://github.com/cheyiliu/AsyncCmdForAndroid