為什么要用路由框架,路由框架哪些好處等等勋颖,在此就不做解釋
最常用的框架是ARouter
那是不是可以自己寫一個路由框架呢宙暇,不參考ARouter的方式
首先說說 模塊化
每個模塊各自維護(hù)自己的跳轉(zhuǎn)或其他規(guī)則(如打開相機(jī))
先定義一個模塊處理器,用來處理上訴規(guī)則
這個模塊處理器需要如下功能:
- 運(yùn)行路由url入口
- 對象傳遞
- 預(yù)處理url
- 解析url
- 處理解析后結(jié)果
以上步驟,開放給調(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