Android-自定義Router(路由)

參考資料:https://mp.weixin.qq.com/s/itAuv86OsTHfBahUrk21DA

我們知道Android的組件化離不開Router,路由的主要主要作用是:消息的中轉站,為我們的項目多模塊的依賴解耦。,當然市面上有三方路由框架,比如阿里的ARouter就是一個不錯的選擇,但我們還是要自己自定義一個Router,來研究一下,畢竟自己動手豐衣足食嘛,ok,我們進入正題。

項目分析

這是我demo的項目結構:


image.png

當然凡是用到路由的項目,其依賴關系一定復雜,但我們這里只是為了講解路由的實現,所以就項目的耦合度并不高。
主要是app,fifferentprocess,sameprocessmodule這三個模塊的依賴,通過自定義router實現解耦,common模塊就是依賴模塊常用的一些靜態變量統一存放,便于管理。

router模塊的主要代碼分析

我們說了router主要作用是消息的中轉站,所以我們先看一下其內部的構成類:


image.png

沒錯就是這五個類,其中的MainActivity里啥也沒有,也就是Xaction,Xrouter,XrouterRequest,XrouterResponse這四個類,是不是很簡單,那我們就來逐一分析一下。

Xrouter

Xrouter是router模塊的消息中轉類,專門處理消息。我們看其代碼:

  private static final String TAG = "Xrouter";

    //使用volatile關鍵字的好處是保證線程可見
    public static volatile Xrouter  mXrouter ;
    //使用HashMap初始化一個隊列mXactions,用來存儲不同種類的消息通道
    public static HashMap<String,Xaction> mXactions ;


    private  Xrouter() {
        mXactions =new HashMap<>();
    }

//單例模式,支持多線程。參考:http://www.lxweimin.com/p/769f2593c94e
    public static Xrouter getInstance(){
        if(mXrouter == null){
           synchronized (Xrouter.class){
               if(mXrouter == null){
                   mXrouter =new Xrouter();
               }
           }
        }
        return mXrouter;
    }


    //往消息隊列插入不同消息通道的方法,這里參數包括通道名稱和通道本身Xaction.java
    public  void registerAction(String actionKey,Xaction xaction){
        if(mXactions.containsKey(actionKey)){
            Log.e(TAG, "該通道已經注冊");
        }else{
            mXactions.put(actionKey,xaction);
        }

    }



    //對應通道發送消息的方法
    public  XrouterResponse senMessage(Context context ,XrouterRequest xrouterRequest){
       XrouterResponse mXrouterResponse=new XrouterResponse();
       Xaction mXaction =getmXAction(xrouterRequest.getActionName());
       //Xaction對象不為空,說明該通道存在,之前已經注冊,可以正常發送消息
       if(mXaction != null){
           //將發送的消息內容(xrouterRequest.getData())傳遞給對應的Xaction的實現類
           Object mObject =mXaction.startAction(context,xrouterRequest.getData());
           mXrouterResponse.setResponseResult(XrouterResponse.RESPONSE_SUCCESS_CODE,XrouterResponse.RESPONSE_SUCCESS,mObject);

       }else{
           mXrouterResponse.setResponseResult(XrouterResponse.RESPONSE_FAIL_CODE,XrouterResponse.RESPONSE_FAIL,"該Xaction沒有創建");

       }

     return mXrouterResponse;
    }


    //返回消息通道對應的對象
    public Xaction  getmXAction(String actionName){
        if(mXactions.containsKey(actionName)){
            return mXactions.get(actionName);
        }
        return null;
    }

注釋都很詳細,主要是三個方法registerAction(),senMessage()和 getmXAction()方法,既然是消息的中轉站那么就要存儲消息,我們這里用HashMap<String,Xaction>的一個HashMap來存消息Xaction.
分別來說一下這三個方法

  • registerAction()
    我們在用HashMap存消息之前先要注冊消息對象,而registerAction方法通過key,value的形式把我們的Xaction放入HashMap存儲起來,完成注冊。

  • senMessage()
    這個方法比較重要,簡單來說就是我們發消息給相關的module.,里面涉及的XrouterResponse,Xaction,Xrespinse我們稍后說。

  • getmXAction()
    此方法就是查找我們之前在HashMap中注冊的消息即Xaction是否已經存在,存在就返回其對象。

Xaction
image.png

Xaction是抽象類,里面包含一個抽象方法startAciont,此抽象方法主要是讓實現類對發送消息做做一個傳遞,也就是將發送的消息傳遞給對應的module,并返回結果(是否成功將消息傳遞)。

XrouterRequest
public class XrouterRequest {

    //消息通道名稱
    private String  mActionName;
    //消息通道攜帶的數據
    private HashMap<String ,Object > mData;


    private XrouterRequest(){
        mData =new HashMap<>();
    }

    public static XrouterRequest create(){
        return new XrouterRequest();
    }


     public XrouterRequest putData(String key, Object value){
         mData.put(key,value);
         return this;
     }

    public XrouterRequest putActionName(String actionName){
        mActionName=actionName;
        return this;
    }


     public String getActionName(){
        return this.mActionName;
     }


     public HashMap<String ,Object> getData(){
        return this.mData;
     }


}

發送消息的載體,也就是具體消息也攜帶的內容,包括兩個變量一個是mActionName,此mActionName和注冊到HashMap中的Xaction的key對應,便于查找到Xaction對象,而其中的mData這是攜帶傳遞的內容。

XrouterResponse
public class XrouterResponse {

    public static final String RESPONSE_SUCCESS="發送消息成功";
    public static final String RESPONSE_FAIL="發送消息失敗";
    public static final  int RESPONSE_SUCCESS_CODE=1;
    public static final  int RESPONSE_FAIL_CODE=0;


    //狀態碼
     private int mcode;
     //描述:消息發送成功或失敗
     private String mdes;
     //消息反饋的其他信息
     private Object mbody;



     //獲取響應消息
     public JSONObject getResponseResult(){
         JSONObject mJSONObject=null;
         try {
             mJSONObject =new JSONObject();
             mJSONObject.put("code",mcode).put("des",mdes).put("content",mbody);
         } catch (JSONException e) {
             e.printStackTrace();
         }
         return mJSONObject;
     }



     //設置響應消息
     public  void setResponseResult(int code ,String des,Object obj){
         this.mcode=code;
         this.mdes=des;
         this.mbody=obj;
     }
}

消息的發送結果的響應類,主要由狀態碼,描述和其他反饋信息三部分構成。包含一個獲取消息結果一個設置消息結果的方法,沒啥好說的。

differentprocess和sameprocess模塊

從字面意思來看他們一個是和app在一個進程中,一個不再一個進程中。這里主要是為了測試如果不在同一個進程中路由的效果,不再進程中主要是因為我在differentprocess模塊的功能清單文件中添加了:


image.png

這兩個模塊(differentprocess和sameprocess)都實現了Xaction的抽象通道方法startAction,j具體如下:


image.png

這樣就可以將消息通過通道傳遞給相應的activity了。而在activity中,我們只是對傳遞的內容進行了展示,如下:

image.png

common模塊

沒事說的,就是幾個常量,自己下載demo看。

app模塊

該模塊中兩個類
-MainActivity中

public class MainActivity extends AppCompatActivity {
 Button btn_sameProcess;
 Button btn_differentProcess;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn_sameProcess=findViewById(R.id.sameprocess);
    btn_differentProcess=findViewById(R.id.differnetprocess);

    btn_differentProcess.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //封裝傳遞的請求數據到XrouterRequest
            XrouterRequest mXrouterRequest =XrouterRequest.create().putData("data","發給不同進程的數據測試").putActionName(DifferentProcessActionMessage.DIFFERENTPROCESSACTIONNAME);
            XrouterResponse mXrouterResponse=Xrouter.getInstance().senMessage(MainActivity.this,mXrouterRequest);
            Toast.makeText(MainActivity.this,mXrouterResponse.getResponseResult()+"",Toast.LENGTH_LONG).show();

        }
    });
    btn_sameProcess.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //封裝傳遞的請求數據到XrouterRequest
            XrouterRequest mXrouterRequest =XrouterRequest.create().putData("data","發給同進程的數據測試").putActionName(SameProcessActionMessage.SANEPORICESSBANE);
            XrouterResponse mXrouterResponse=Xrouter.getInstance().senMessage(MainActivity.this,mXrouterRequest);
            Toast.makeText(MainActivity.this,mXrouterResponse.getResponseResult()+"",Toast.LENGTH_LONG).show();

        }
    });
}}

MainActivty就是兩個按鈕一個是跳轉到同進程一個跳轉到不同進程的module中,將攜帶的信息存放到XrouterRequest中,同時返回響應對象XrouterResponse,簡單toast了一下。

  • BaseApplication
    Xaction消息的注冊建議存放點Application中,如下:
public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //通道的初始化最好放在Application中
        initAction();
    }

        private void initAction() {
            Xrouter.getInstance().registerAction(DifferentProcessActionMessage.DIFFERENTPROCESSACTIONNAME,new com.hxzk.bj.differnertprocess.action.DifferentProcessAction());
           Xrouter.getInstance().registerAction(SameProcessActionMessage.SANEPORICESSBANE,new com.hxzk.bj.sameprocessmodule.action.SameProcessAction());
    }

}

就這么多,建議大家下載demo具體查看,以上傳github:點我傳送

告辭!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容