亚洲成在人线在线播放无码vr|亚洲成熟女同—区二区三区|日韩精品一区二区中文在线|97欧美精品一区二区三区

  • <strike id="14xru"></strike>
  • <object id="14xru"></object>

  • <th id="14xru"></th>
      <strike id="14xru"><video id="14xru"></video></strike>
      1. 湖北企業(yè)新聞網(wǎng),歡迎您!

        幫助中心 廣告聯(lián)系

        網(wǎng)站關(guān)鍵詞: 湖北企業(yè)新聞網(wǎng)

        Android 組件化路由框架設(shè)計(jì)(仿Arouter)!

        來(lái)源:時(shí)間:2020-11-20 08:23:17 閱讀:-


        前言

        在組件化開(kāi)發(fā)中一個(gè)必須要面對(duì)的問(wèn)題就是組件間頁(yè)面跳轉(zhuǎn),實(shí)現(xiàn)的方法有很多,簡(jiǎn)單的可以通過(guò)反射獲取,但是比較耗費(fèi)性能,也可以通過(guò)隱式跳轉(zhuǎn),但是隨著頁(yè)面的增多,過(guò)濾條件會(huì)隨之增多,后期維護(hù)麻煩。那還有什么方法呢,沒(méi)錯(cuò),就是接下來(lái)要介紹的Arouter路由框架,該框架是阿里巴巴開(kāi)源項(xiàng)目,大廠出品,必屬精品。使用過(guò)Arouter得同學(xué)都知道Arouter是通過(guò)給每個(gè)頁(yè)面添加@Route注解然后調(diào)用一定的方法實(shí)現(xiàn)跳轉(zhuǎn)的,而Arouter的核心就是這個(gè)注解。
        ??這里要介紹一個(gè)概念,APT(Annotation Processing Tool)即注解處理器,是一種處理注解的工具,它用來(lái)在編譯時(shí)掃描和處理注解,注解處理器以Java代碼(或者編譯過(guò)的字節(jié)碼)作為輸入,生成.java文件作為輸出。簡(jiǎn)單來(lái)說(shuō)就是在編譯期,通過(guò)注解生成.java文件。
        ??Arouter的路由表就是在該工具下在編譯期生成的,說(shuō)簡(jiǎn)單了,就是利用注解在編譯期生成了一些java文件,我們?cè)谶@些新的java文件中將所有被注解的頁(yè)面添加進(jìn)了路由表中。


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        設(shè)計(jì)思路

        arouter-compiler:注解編譯處理器,引入“arouter-annotation”,在編譯器把注解標(biāo)注的相關(guān)目標(biāo)類(lèi)生成映射文件,包含路由框架所使用的全部注解,及其相關(guān)類(lèi)
        arouter-api:實(shí)現(xiàn)路由控制


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        實(shí)現(xiàn)效果


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        步驟

        • 新建module java library(router_compiler)(因?yàn)樵谥?Module 中無(wú)法找到 AbstractProcessor 類(lèi))


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)


        • 新建module android library(router_api),步驟如上,但是要注意選擇Android library。
        • 在route-compiler的gradle文件中導(dǎo)入依賴(lài)和jdk版本支持
        apply plugin: 'java-library'dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    api 'com.squareup:javapoet:1.11.1'    api 'org.apache.commons:commons-collections4:4.4'    api 'org.apache.commons:commons-lang3:3.5'}sourceCompatibility = "8"targetCompatibility = "8"
      2. 在app工程gradle文件中添加jdk版本支持
      3. compileOptions {    sourceCompatibility 1.8    targetCompatibility 1.8}
        • 在route_api和app模塊等其他組件化模塊的gradle文件中導(dǎo)入route_compiler模塊
        annotationProcessor project(':router_compiler')api project(':router_compiler')
        • 在每個(gè)module模塊中的gradle文件中添加下列語(yǔ)句用來(lái)獲取每個(gè)module的包名
        javaCompileOptions {    annotationProcessorOptions {        arguments = [ROUTER_MODULE_NAME: project.getName()]    }}
        • 在router_compiler模塊中創(chuàng)建RouteProcessor類(lèi)并繼承自AbstractProcessor
        • 在router_compiler模塊中的main文件夾下創(chuàng)建文件夾resources/META-INF/services,然后創(chuàng)建javax.annotation.processing.Processor文件,并添加下列語(yǔ)句
        com.nsyw.routerdemo.router_compiler.RouteProcessor
        • 在router-compiler根目錄下新建注解類(lèi)Route
        public @interface Route {    /**     * Path of route     */    String path();}
        • 創(chuàng)建接口IRoute,自動(dòng)生成的java文件都要繼承自該接口
        public interface IRoute {    /**     *     * @param routes 模塊下的路由集合     */    void loadInto(Map routes);}
        • RouteProcessor.java
        /** * @SupportedAnnotationTypes表示支持的注解類(lèi)型 */@SupportedAnnotationTypes("com.nsyw.routerdemo.router_compiler.annotation.Route")public class RouteProcessor extends AbstractProcessor {        ......    @Override    public synchronized void init(ProcessingEnvironment processingEnvironment) {        ......    }    @Override    public boolean process(Set set, RoundEnvironment roundEnvironment) {                   ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(                    ClassName.get(Map.class),                    ClassName.get(String.class),                    ClassName.get(RouteMeta.class)            );            ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "routes").build();            /*              methodBuilder 方法名              addAnnotation 方法添加注解              addModifiers  方法訪問(wèn)限制類(lèi)型              addParameter  添加參數(shù)             */            MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)                    .addAnnotation(Override.class)                    .addModifiers(PUBLIC)                    .addParameter(groupParamSpec);            ClassName routeMetaCn = ClassName.get(RouteMeta.class);            ClassName routeTypeCn = ClassName.get(RouteType.class);            //遍歷@Route注解的所有Activity            for (Element element : routeElements) {                TypeMirror tm = element.asType();                //獲取注解                Route route = element.getAnnotation(Route.class);                RouteMeta routeMeta = null;                if (types.isSubtype(tm, type_Activity)) {                    routeMeta = new RouteMeta(route.path(), RouteType.ACTIVITY);                }                //獲取被注解的類(lèi)的類(lèi)名                ClassName className = ClassName.get((TypeElement) element);                /*                  方法內(nèi)的添加路由語(yǔ)句                  routes.put(routeMeta.getPath(),RouteMeta.build(routeMeta.getPath(),RouteType.ACTIVITY,className.class))                 */                loadIntoMethodOfGroupBuilder.addStatement(                        "routes.put($S,$T.build($S,$T." + routeMeta.getRouteType() + ", $T.class))",                        routeMeta.getPath(),                        routeMetaCn,                        routeMeta.getPath(),                        routeTypeCn,                        className);            }            /*              構(gòu)建java文件             */            try {                JavaFile.builder(PACKAGE_OF_GENERATE_FILE,                        TypeSpec.classBuilder(NAME_OF_ROUTE + moduleName)                                .addJavadoc(WARNING_TIPS)                                .addSuperinterface(ClassName.get(mElementsUtil.getTypeElement(IROUTE_LOAD)))                                .addModifiers(PUBLIC)                                .addMethod(loadIntoMethodOfGroupBuilder.build())                                .build()                ).build().writeTo(mFiler);            } catch (IOException e) {                e.printStackTrace();            }            return true;        }        return false;    }}
        • 在router_api模塊下創(chuàng)建Router
        public class Router {    private static volatile Router mInstance = new Router();    private Context mContext;    private String path;    private Map map = new HashMap<>();    public static void init(Application application) {        mInstance.mContext = application;        Set routerMap;        try {            routerMap = ClassUtils.getFileNameByPackageName(mInstance.mContext, consts.PACKAGE_OF_GENERATE_FILE);            Log.e("Router", routerMap.toString());            for (String className : routerMap) {                ((IRoute) (Class.forName(className).getConstructor().newInstance())).loadInto(mInstance.map);            }        } catch (PackageManager.NameNotFoundException | InterruptedException | IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {            e.printStackTrace();        }    }    public static synchronized Router getInstance() {        return mInstance;    }    public Router build(String path) {        mInstance.path = path;        return mInstance;    }    public void navigation(Context context) {        RouteMeta routeMeta = mInstance.map.get(mInstance.path);        if (routeMeta != null) {            context.startActivity(new Intent(context, routeMeta.getClazz()));        }    }}
        • Router需要在Application中初始化
        public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        Router.init(this);    }}

        在AndroidManifest文件的application節(jié)點(diǎn)添加下列語(yǔ)句

        android:name=".MyApplication"
        • 項(xiàng)目build的完之后會(huì)在各個(gè)模塊的相應(yīng)的文件夾下生成java文件,這些文件會(huì)被Router依次獲取將路由信息存入路由表中。


        Android 組件化路由框架設(shè)計(jì)(仿Arouter)

        以下代碼是編譯器自動(dòng)生成的

        package com.nsyw.routerdemo.routes;import com.nsyw.routerdemo.MainOneActivity;import com.nsyw.routerdemo.MainTwoActivity;import com.nsyw.routerdemo.router_compiler.IRoute;import com.nsyw.routerdemo.router_compiler.RouteMeta;import com.nsyw.routerdemo.router_compiler.RouteType;import java.lang.Override;import java.lang.String;import java.util.Map;/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */public class Router$$App$$app implements IRoute {  @Override  public void loadInto(Map routes) {    routes.put("/main/one",RouteMeta.build("/main/one",RouteType.ACTIVITY, MainOneActivity.class));    routes.put("/main/two",RouteMeta.build("/main/two",RouteType.ACTIVITY, MainTwoActivity.class));  }}
        • 使用
        Router.getInstance().build("/main/one").navigation(MainActivity.this);

        小結(jié)

        Router只是參照ARouter手動(dòng)實(shí)現(xiàn)的路由框架,剔除掉了很多東西,只實(shí)現(xiàn)了組件間Activity之間的跳轉(zhuǎn),如果想要用在項(xiàng)目里,建議還是用ARouter更好,畢竟這只是個(gè)練手項(xiàng)目,功能也不夠全面,當(dāng)然有同學(xué)想對(duì)demo擴(kuò)展后使用那當(dāng)然更好,遇到什么問(wèn)題可以及時(shí)聯(lián)系我。我的目的是通過(guò)自己手動(dòng)實(shí)現(xiàn)路由框架來(lái)加深對(duì)知識(shí)的理解,如這里面涉及到的知識(shí)點(diǎn)apt、javapoet和組件化思路、編寫(xiě)框架的思路等??吹竭@里,如果感覺(jué)干貨很多,歡迎關(guān)注我的github,里面會(huì)有更多干貨!

        推薦閱讀:易浪網(wǎng)