Android 路由框架

為什么要用路由框架,路由框架哪些好處等等勋颖,在此就不做解釋
最常用的框架是ARouter
那是不是可以自己寫一個路由框架呢宙暇,不參考ARouter的方式

首先說說 模塊化
每個模塊各自維護(hù)自己的跳轉(zhuǎn)或其他規(guī)則(如打開相機(jī))
先定義一個模塊處理器,用來處理上訴規(guī)則
這個模塊處理器需要如下功能:

  • 運(yùn)行路由url入口
  • 對象傳遞
  • 預(yù)處理url
  • 解析url
  • 處理解析后結(jié)果
企業(yè)微信截圖_15919320138763.png

以上步驟,開放給調(diào)用者只需要解析url這一步

public abstract class AbsRouterProcessor implements IProcessInterface<RouterAction> {
   //這是外部調(diào)用的入口
 @Override
    public boolean execute(Context context, String url, IRouterHandler handler, IResultCallback callback, IRouterConfig routerConfig) throws RouterException{
        mContext = context;
        RouterAction action = processUrl(url, routerConfig);
        return processResult(action, handler, callback);
    }
}

處理url

processUrl 中主要做了預(yù)處理和解析url,來得到最終的RouterAction傻粘,交給結(jié)果處理器去處理:

    private RouterAction processUrl(String url, IRouterConfig routerConfig) throws RouterException{
        RouterAction action = preprocess(url, routerConfig);
        process(action);
        return action;
    }

    protected RouterAction preprocess(String url, IRouterConfig routerConfig) throws RouterException{
        CommPreProcessor preProcessor = new CommPreProcessor(mContext);
        RouterAction action = preProcessor.prePorcess(url, routerConfig);
        return action;
    }

    protected void process(RouterAction action) throws RouterException{
        mapping(mContext, action);
        action.setBundle(bundle);
    }
  • RouterAction:先來看下RouterAction,主要是給后續(xù)處理器封裝的對象帮掉,看看其定義的結(jié)構(gòu):
    private int requestCode;// activity requestCode
    private String packageName;// 傳遞參數(shù)(多進(jìn)程使用)
    private String originalUrl;//原始url
    private int targetType;//目標(biāo)類型弦悉,有activity,fragment或自定義類型
    private Bundle bundle;//供大對象使用
    private T target;//目標(biāo)對象蟆炊,activity為Intent稽莉,fragment為Fragment
    private String path;//url path
    private Parameters parameters;//url 參數(shù)
    private int intentFlag;//如果是intent,代表intentFlag
  • IRouterConfig 定義了此次路由的SCHEME和HOST盅称,由調(diào)用者初始化時傳遞進(jìn)來
public interface IRouterConfig extends RouterConfig {
    String getScheme();
    String getHost();
    String getPackageName();
}
  • CommPreProcessor是自帶的預(yù)處理器肩祥,也可以自定義預(yù)處理器
public class CommPreProcessor implements IPreProcessInterface<RouterAction> {
...
 @Override
    public RouterAction prePorcess(String url, IRouterConfig routerConfig) throws RouterException {
       //將url轉(zhuǎn)化為RouterAction 
    }
}
  • mapping方法是調(diào)用這需要override的方法,主要是實(shí)現(xiàn)匹配規(guī)則

比如我們定義了一個Home的Module缩膝,則需要自定一個Processor:

public class HomeRouteProcessor extends AbsRouterProcessor {
    @Override
    protected void mapping(Context context, RouterAction action) {
       if("/open/native/home".equals(path)) {
            action.setTargetType(RouterAction.TYPE_ACTIVITY);
            Intent intent = new Intent(mContext, HomeActivity.class);
            action.setTarget(intent);
        } else if(...) {
             ...
        }
    }
}

處理結(jié)果

得到RouterAction后混狠,就可以處理結(jié)果了,再此疾层,調(diào)用這可以自定義處理器将饺,如果不傳入自定義處理器,工程則會處理Activity痛黎,F(xiàn)ragment和Service三種類型
傳入自定義處理器:
在入口函數(shù)execute中傳入
1.自定義處理器
2.結(jié)果接收器

@Override
    public boolean execute(Context context, String url, IRouterHandler handler, IResultCallback callback, IRouterConfig routerConfig) throws RouterException{
}

處理器只需實(shí)現(xiàn)IRouterHandler接口
拿ActivityHandler舉例:

public class ActivityHandler implements IRouterHandler {

    public boolean handle(final Context context, RouterAction action, final IResultCallback callback) throws RouterException {
        ...
       Parameters parameters = action.getParameters();
        if(parameters != null) {
           //parameters 處理
        }
        Bundle bundle = action.getBundle();
        //bundle 處理

        //intent flag
       int flag = action.getIntentFlag();
        if(flag > 0) {
            intent.addFlags(flag);
        }
        final int requestCode = action.getRequestCode();
         new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                 if (context instanceof Activity) {
                     if(requestCode > 0) {
                         ((Activity) context).startActivityForResult(intent, requestCode);
                      } else {
                         context.startActivity(intent);
                     }
                } else {
                    context.startActivity(intent);
                }
                if (null != callback) { // Navigation over.
                    callback.onResult(true);
                }
            }
        });
    }
}

注意:此處結(jié)果接收器callback返回的是true予弧,如果是fragment,此處返回的就是fragment對象湖饱,如果是自定義IRouterHandler 掖蛤,callback返回的則是自定義對象

以上則是整個處理流程
但還有一步就是注冊

注冊

首先定義一個對外類UrlRouteManager,功能相當(dāng)于接口

  • 注冊
  • 注銷
  • 查找
public class UrlRouteManager {
    private UrlRouterCore core;
    public void registerProtocol(String path, int group, IProcessInterface processor) throws RouterException{
        if(core == null) {
            throw new RouterException("please call init method first");
        }
        core.registerProtocol(path, group, processor);
    }

    public void unRegisterProtocol(int group) throws RouterException{
        if(core == null) {
            throw new RouterException("please call init method first");
        }
        core.unRegisterProtocol(group);
    }
  
   public IProcessInterface seek(String url, int group) throws RouterException{
        if(core == null) {
            throw new RouterException("please call init method first");
        }
        return core.getTargetIProcessor(url, group);
    }
}

真正實(shí)現(xiàn)的是UrlRouterCore這個類

public void registerProtocol(String regx, int group, IProcessInterface processor) throws RouterException{
        ...
        Map<String, IProcessInterface> map = processorList.get(group);
        if(map == null)
            map = new HashMap<String, IProcessInterface>();
        map.put(regx, processor);
        processorList.put(group, map);
    }

以group為分組井厌,將processor放到一個SparseArray中
看下seek的實(shí)現(xiàn)

public IProcessInterface getTargetIProcessor(String url, int group) {
        Map<String, IProcessInterface> map = processorList.get(group);
        if(map == null) {
            return null;
        }
        IProcessInterface processInterface = null;
        Iterator iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, IProcessInterface> entry = (Map.Entry<String, IProcessInterface>) iter.next();
            String key = entry.getKey();
            IProcessInterface val = entry.getValue();
            String[] strArray = MathUtils.getMatchStr(url, key);
            if(strArray != null && strArray.length > 0) {
                processInterface = val;
                break;
            }
        }
        return processInterface;
    }

根據(jù)分組和url找到對應(yīng)的IProcessInterface 蚓庭,在execute函數(shù)執(zhí)行時致讥,會自動運(yùn)行找到對應(yīng)的IProcessInterface

看看調(diào)用者如何注冊:
步驟一:定義module的注冊器,并將processor綁定

public class HomeModuleRegister extends ProcessorRegister {
    private String regex1 = RobinRouterConfig.SCHEME + "://" + RobinRouterConfig.HOST + "/open/native/home/tab1";
    private String regex2 = RobinRouterConfig.SCHEME + "://" + RobinRouterConfig.HOST + "/open/native/home";
 private int group = RobinRouterConfig.GROUP_HOME;
@Override
    public void register() {
        HomeRouteProcessor processor = new HomeRouteProcessor();
        UrlRouteManager.getInstance().init(new RobinRouterConfig());
        try {
            UrlRouteManager.getInstance().registerProtocol(regex1, group, processor);
            UrlRouteManager.getInstance().registerProtocol(regex2, group, processor);
        } catch (RouterException e) {
            e.printStackTrace();
        }
    }
}

步驟二:在application中初始化與注冊

public class DemoApplication extends Application {
    private ProcessorRegister processorRegister;
    @Override
    public void onCreate() {
        super.onCreate();

        //注冊
        processorRegister = new HomeModuleRegister();
        processorRegister.register();
    }
}

末尾

大致實(shí)現(xiàn)思路就如上述所說
使用方式在github上有詳細(xì)說明
源碼地址 https://github.com/robinfjb/Android-Router

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市器赞,隨后出現(xiàn)的幾起案子垢袱,更是在濱河造成了極大的恐慌,老刑警劉巖港柜,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件请契,死亡現(xiàn)場離奇詭異,居然都是意外死亡夏醉,警方通過查閱死者的電腦和手機(jī)爽锥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來授舟,“玉大人救恨,你說我怎么就攤上這事∈褪鳎” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵擎淤,是天一觀的道長奢啥。 經(jīng)常有香客問我,道長嘴拢,這世上最難降的妖魔是什么桩盲? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮席吴,結(jié)果婚禮上赌结,老公的妹妹穿的比我還像新娘。我一直安慰自己孝冒,他們只是感情好柬姚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庄涡,像睡著了一般量承。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上穴店,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天撕捍,我揣著相機(jī)與錄音,去河邊找鬼泣洞。 笑死忧风,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的球凰。 我是一名探鬼主播狮腿,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼该窗,長吁一口氣:“原來是場噩夢啊……” “哼扬跋!你這毒婦竟也來了悍及?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤墩崩,失蹤者是張志新(化名)和其女友劉穎昧绣,沒想到半個月后规肴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夜畴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年拖刃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贪绘。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡兑牡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出税灌,到底是詐尸還是另有隱情均函,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布菱涤,位于F島的核電站苞也,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏粘秆。R本人自食惡果不足惜如迟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望攻走。 院中可真熱鬧殷勘,春花似錦、人聲如沸昔搂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巩趁。三九已至痒玩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間议慰,已是汗流浹背蠢古。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留别凹,地道東北人草讶。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像炉菲,于是被迫代替她去往敵國和親堕战。 傳聞我的和親對象是個殘疾皇子坤溃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容