組件化4---組件之間相互跳轉的邏輯實現

完整組化件和插件化可以參考我的github項目,已經用在線上項目中

上面三篇文章我們已經瞭解了組件化的原理和一些跳轉思路,下面我們就一步一步來搭建我們的組件化架構.

首先是環境的搭建,可以參考上面三篇文章

其次是搭建apt環境

1: 創建一個java模塊compile,配置相應依賴,下面是配置

import javax.tools.JavaCompiler

apply plugin: 'java-library'

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
    implementation 'com.squareup:javapoet:1.9.0'
    implementation project(':ancely_annotation')
}

tasks.withType(JavaCompiler) {
    options.encoding = 'UTF-8'
}
sourceCompatibility = "7"
targetCompatibility = "7"

2,創建一個類AncelyProcess繼承AbstractProcessor,生成代碼邏輯主要在這個類裏面

3, 再創建一個類生成的註解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface ARouter {

    String path();

    String group() default "";
}

4, 再創建一個RouterBean,保存了所有還有@ARouter註解的類的一些信息

public class RouteBean {
    public enum Type {
        ACTIVITY, CALL, FRAGMENT_V4
    }

    //枚舉類型
    private Type type;

    //類節點
    private Element element;

    //被ARoute註解的對象
    private Class<?> clazz;

    //路由的組名
    private String group;

    //路由的地址
    private String path;
}

5,最後我們要生成的二個類的形式爲下面,每一個Model裏面如果有就會在每個Model下生成對應的二個類文件,生成下面二個類的代碼就不介紹,生成順序爲先生成ARoute$$Path$$app,然後再生成ARoute$$Group$$app,因爲我們要將ARoute$$Path$$app這個類對應到我們的組裏去

想要看完整生成代碼的邏輯,可以去我github上

AncelyProcess


public class ARoute$$Path$$app implements ARouteLoadPath {
  @Override
  public Map<String, RouteBean> loadPath() {
    Map<String,RouteBean> pathMap = new HashMap<>();
    pathMap.put("/app/TextModelActivity",RouteBean.create(RouteBean.Type.ACTIVITY,TextModelActivity.class,"/app/TextModelActivity","app"));
    pathMap.put("/app/TextFragment",RouteBean.create(RouteBean.Type.FRAGMENT_V4,TextFragment.class,"/app/TextFragment","app"));
    pathMap.put("/app/MainActivity",RouteBean.create(RouteBean.Type.ACTIVITY,MainActivity.class,"/app/MainActivity","app"));
    return pathMap;
  }
}



public class ARoute$$Group$$app implements ARouteLoadGroup {
  @Override
  public Map<String, Class<? extends ARouteLoadPath>> loadGroup() {
    Map<String,Class<? extends ARouteLoadPath>> groupMap = new HashMap<>();
    groupMap.put("app",ARoute$$Path$$app.class);
    return groupMap;
  }
}

類生成完了也就是相應的路由都配置好,這樣就開始做路由的管理,也就是界面相互跳轉相互傳參的操作,新建路由管理類RouterManager

public class RouterManager {
    private String mGroup;
    private String mPath;
    private static RouterManager sInstance;

    private LruCache<String, ARouteLoadGroup> mGroupLruCache; //組緩存
    private LruCache<String, ARouteLoadPath> mPathLruCache; // 跳轉地址緩存
    private static final String GROUP_FILE_PREFFIX_NAME = "ARoute$$Group$$";

    private RouterManager() {
        mGroupLruCache = new LruCache<>(163);//最大條目爲163
        mPathLruCache = new LruCache<>(163);//最大條目爲163
    }

    public static RouterManager getInstance() {
        if (sInstance == null) {
            synchronized (RouterManager.class) {
                if (sInstance == null) {
                    sInstance = new RouterManager();
                }
            }
        }
        return sInstance;
    }
}

從上面幾個成員變量可以看出來,我們對組和組對應的pah做了相應的緩存,將獲取到的組,我組對應的path添加到相應緩存的代碼如下

    public Object navigation(Context context, BundleManager bundleManager, int code) {
        if (bundleManager.isFinish()) {
            Intent intent = new Intent();
            if ((bundleManager.getBundle() != null)) intent.putExtras(bundleManager.getBundle());
            ((Activity) context).setResult(code, intent);
            ((Activity) context).finish();
            return null;
        }
        //獲取對應組類文件的全類名比如com.ancely.fyw.modular.apt.ARoute$$Group$$app
        String groupClassName = "com.ancely.fyw.modular.apt." + GROUP_FILE_PREFFIX_NAME + mGroup;
        Log.e("ancely>>> :", groupClassName);
        try {
            //讀取group的類文件 懶加載方式 如果只打開app只只加載app裏的
            ARouteLoadGroup loadGroup = mGroupLruCache.get(mGroup);
            if (loadGroup == null) {
                //加載APT  groutp類文件 如: ARouter$$Group$$app
                Class<?> clazz = Class.forName(groupClassName);
                loadGroup = (ARouteLoadGroup) clazz.newInstance();
                //添加到緩存裏
                mGroupLruCache.put(mGroup, loadGroup);
            }
            //判空
            if (loadGroup.loadGroup().isEmpty()) {
                throw new RuntimeException("arouter group 加載失敗");
            }
            //讀取path
            ARouteLoadPath loadPath = mPathLruCache.get(mPath);
            if (loadPath == null) {
                //通過group加載接口,去獲取path加載接口
                Class<? extends ARouteLoadPath> clazz = loadGroup.loadGroup().get(mGroup);

                if (clazz != null) loadPath = clazz.newInstance();
                if (loadPath != null) mPathLruCache.put(mPath, loadPath);
            }

            if (loadPath != null) {
                if (loadPath.loadPath().isEmpty()) {
                    throw new RuntimeException("arouter path 加載失敗");
                }
                RouteBean routeBean = loadPath.loadPath().get(mPath);
                if (routeBean != null) {
                    //類型判斷
                    switch (routeBean.getType()) {
                        case ACTIVITY:
                            Intent intent = new Intent(context, routeBean.getClazz());
                            intent.putExtras(bundleManager.getBundle());

                            if (bundleManager.isResult()) {
                                ((Activity) context).setResult(code, intent);
                            }

                            if (code > 0) {//跳轉的時候需要回調
                                ((Activity) context).startActivityForResult(intent, code, bundleManager.getBundle());

                            } else {
                                context.startActivity(intent, bundleManager.getBundle());
                            }
                            break;
                        case CALL:
                            //返回的是一個接口的實現類
                            return routeBean.getClazz().newInstance();

                        case FRAGMENT_V4:
                            Fragment fragment = (Fragment) routeBean.getClazz().newInstance();
                            fragment.setArguments(bundleManager.getBundle());
                            return fragment;
                        default:

                            break;
                    }
                } else {
                    Toast.makeText(context, "功能暫未開放", Toast.LENGTH_SHORT).show();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

這樣我們就可以直接使用了

RouterManager.getInstance().build("/login/Login_MainActivity1").xxx.
.navigation(this, 20);就可以完成跳轉
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章