參考資料:https://mp.weixin.qq.com/s/itAuv86OsTHfBahUrk21DA
我們知道Android的組件化離不開Router,路由的主要主要作用是:消息的中轉站,為我們的項目多模塊的依賴解耦。,當然市面上有三方路由框架,比如阿里的ARouter就是一個不錯的選擇,但我們還是要自己自定義一個Router,來研究一下,畢竟自己動手豐衣足食嘛,ok,我們進入正題。
項目分析
這是我demo的項目結構:
當然凡是用到路由的項目,其依賴關系一定復雜,但我們這里只是為了講解路由的實現,所以就項目的耦合度并不高。
主要是app,fifferentprocess,sameprocessmodule這三個模塊的依賴,通過自定義router實現解耦,common模塊就是依賴模塊常用的一些靜態變量統一存放,便于管理。
router模塊的主要代碼分析
我們說了router主要作用是消息的中轉站,所以我們先看一下其內部的構成類:
沒錯就是這五個類,其中的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
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模塊的功能清單文件中添加了:
這兩個模塊(differentprocess和sameprocess)都實現了Xaction的抽象通道方法startAction,j具體如下:
這樣就可以將消息通過通道傳遞給相應的activity了。而在activity中,我們只是對傳遞的內容進行了展示,如下:
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:點我傳送
告辭!