告別onActivityResult,用實現AOP方式獲取startActivityForResult結果
每次我們使用startActivityForResult方法時,如果需要接收返回的結果,總得在onActivityResult中進行處理。如果業務比較複雜,有多個介面攜帶資料返回到同一介面中,需要在 onActivityResult 方法中根據resultCode來判斷到底是從哪個介面返回的,onActivityResult 中塞滿了 if else ,程式碼太臃腫,影響程式碼的閱讀。
下面我們就嘗試用AOP的方式來避免使用onActivityResult,提高程式碼可讀性。
先來看下最終實現的目的碼:
Intent intent = new Intent(MainActivity.this, OneActivity.class); ActivityResultManager.getInstance() .startActivityForResult(MainActivity.this, intent, 100, new ResultCallBack() { @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if(resultCode == Activity.RESULT_OK && data!=null){ String source = data.getStringExtra("source"); textView.setText(source); } } });
可以看到在ActivityResultManager的startActivityForResult方法中添加了一個回撥,回撥方法和Activity的onActivityResult一樣,可以在裡面處理其他介面返回的資料。
startActivityForResult的實現
public interface ResultCallBack { void onActivityResult(int requestCode, int resultCode, @Nullable Intent data); } private HashMap<String, HashMap<Integer,ResultCallBack>> mMap; public void startActivityForResult(Activity context, Intent intent, int requestCode, ResultCallBack callBack){ if(context==null||intent==null) return; if(callBack!=null){ //初始化mMap if(mMap==null) mMap=new HashMap<>(); //mMap中資料的key是Activity的類名,value是resultMap //resultMap中資料的key是requestCode,value是ResultCallBack物件 HashMap<Integer,ResultCallBack> resultMap = mMap.get(context.getClass().getName()); if (resultMap == null) { resultMap = new HashMap<>(); mMap.put(context.getClass().getName(),resultMap); } resultMap.put(requestCode, callBack); } //呼叫Activity的startActivityForResult方法 context.startActivityForResult(intent, requestCode); }
可以看到在startActivityForResult方法中,在呼叫Activity的startActivityForResult方法之前,根據Activity的類名和requestCode,把回撥ResultCallBack的物件存入型別為HashMap<String, HashMap<Integer,ResultCallBack>>的Map中,以便後面可以根據Activity和requestCode獲取ResultCallBack物件,下面先簡單介紹下AOP。
AOP
AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。在Android中實現它的常用工具是AspectJ。AspectJ是AOP的Java語言的實現,是一個程式碼生成工具。
參考 ofollow,noindex">AOP 之 AspectJ 全面剖析 in Android
AspectJ的引入
在library的build.gradle中新增依賴
dependencies { ... implementation 'org.aspectj:aspectjrt:1.8.9' }
在app專案的build.gradle裡應用外掛
apply plugin: 'android-aspectjx'
在專案根目錄的build.gradle裡依賴AspectJX
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
建立Aspect類
建立了一個名為ActivityResultAspect的類,給這個類新增@Aspect註解,程式碼如下:
@Aspect public class ActivityResultAspect { @After("execution(* android.app.Activity.onActivityResult(..))") public void onActivityResultMethod(JoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); int requestCode = (int) args[0]; int resultCode = (int) args[1]; Intent data = (Intent) args[2]; Activity activity = (Activity) joinPoint.getTarget(); ActivityResultManager.getInstance().afterActivityResult(activity, requestCode, resultCode, data); } }
這裡使用execution以Activity的onActivityResult方法執行時為切點,觸發Aspect類。而execution裡面的字串是觸發條件,也是具體的切點。第一個 * 表示任意返回值型別,括號裡的 .. 表示任意多個引數。joinPoint.getArgs()獲取onActivityResult方法的引數,joinPoint.getTarget()獲取連線點所在的目標物件,這裡是Activity。
@After表示切入點之後執行,也就是在Activity的onActivityResult方法執行後,執行我們的onActivityResultMethod方法。這樣每次執行Activity的onActivityResult方法後,就會呼叫我們的onActivityResultMethod方法,在這個方法裡獲取了onActivityResult方法的引數,然後傳入了afterActivityResult方法。
afterActivityResult
public void afterActivityResult(Activity context, int requestCode, int resultCode, Intent data){ if(mMap!=null) { HashMap<Integer, ResultCallBack> resultMap = mMap.get(context.getClass().getName()); if (resultMap != null) { ResultCallBack callBack = resultMap.get(requestCode); if (callBack != null) { callBack.onActivityResult(requestCode, resultCode, data); resultMap.remove(requestCode); if(resultMap.size()==0){ mMap.remove(context.getClass().getName()); if(mMap.size()==0){ mMap=null; } } } } } }
可以看到afterActivityResult方法就是根據Activity和requestCode從mMap中獲取獲取回撥ResultCallBack物件,並呼叫回撥方法。
這樣就可以在回撥方法裡處理其他介面返回的資料了。
總結
1.把回撥ResultCallBack物件根據Activity和requestCode存入Map中。
2.使用AOP方式建立一個Aspect類,以Activity的onActivityResult方法執行時為切點,注入我們的程式碼,獲取onActivityResult的引數,傳入afterActivityResult方法。
3.在afterActivityResult方法中獲取ResultCallBack物件,並呼叫回撥方法。
具體實現方式請看 原始碼

歡迎關注.jpg