仿写Arouter框架实现Activity的跳转

    技术2022-07-11  81

    Arouter 框架是主要由三个模块组成,annotation,compiler,core. annotation :自定义注解,用来声明需要路由的页面(Java Library) compiler :注解解析,在编译时根据自定义注解生成注册路由表的java类(Java Library)。 core : 实现路由跳转功能,供Android调用(Android Library)

    先上工程结构图

    一、annotation模块

    新建一个文件,编写一个注解,声明路由路径

    RouteMeta保存路由信息,通过解析注解获取。

    二、compiler模块

    首先导入依赖的第三方库,compiler模块使用javax的Processor类来解析注解,auto-service自动编译Processor类,使用javapoet库生成java类。

    新建RouterProcessor继承AbstractProcessor类,添加如下注解

     

    初始化RouterProcessor,在process方法中遍历Route注解的节点,如果不为null,进行解析

    获取Activity类的节点信息,然后循环,判断是Activity类型的节点,新建RouteMeta对象保存节点信息。然后调用categories()验证节点的路由地址是否符合规则,再根据分组名保存节点到groupMap中

    遍历groupMap中的节点信息,使用javapoet工具生成一个继承IRouteGroup接口的java类,用来保存每个分组的路由信息。叫分组信息类。

     

    然后遍历所有的分组信息类,生成继承IRouteRoot接口的表信息类,保存分组名对应的分组信息类。

     

    三、core模块

    定义一个路由表保存所有的路由信息

     

    然后,遍历所有的dex文件,查找所有的使用javapoet生成的分组信息类和表信息类。查找是一个耗时操作,使用ThreadPoolExecutor维护一个线程池,来查找所有包名为com.hc.androiddemo.routes 类,并使用使用同步计数器来判断查找是否完成。然后将分组信息类加入Warehouse的groupsIndex中

     

     

    四、跳卡PostCard

    Postcard继承RouteMeta类,保存路由地址、分组名以及要传递的数据。使用Postcard的with方法添加传递的数据,调用Postcard的navigation()进行页面跳转

    public class Postcard extends RouteMeta { private Bundle mBundle; //新版风格 private Bundle optionsCompat; private int flags = -1; public Postcard(String path, String group) { this(path, group, null); } public Postcard(String path, String group, Bundle bundle) { setPath(path); setGroup(group); this.mBundle = (null == bundle ? new Bundle() : bundle); } public Bundle getExtras() {return mBundle;} public Bundle getOptionsBundle() { return optionsCompat; } /** * Intent.FLAG_ACTIVITY** * @param flag * @return */ public Postcard withFlags(int flag) { this.flags = flag; return this; } public Postcard withString(String key,String value){ mBundle.putString(key,value); return this; } public Postcard withInt(String key,int value){ mBundle.putInt(key,value); return this; } public Postcard withBoolean(String key,boolean value){ mBundle.putBoolean(key,value); return this; } public int getFlags() { return flags; } public Object navigation() { return ToolRouter.getInstance().navigation(null, this, -1, null); } public Object navigation(Context context) { return ToolRouter.getInstance().navigation(context, this, -1, null); } public Object navigation(Context context, NavigationCallback callback) { return ToolRouter.getInstance().navigation(context, this, -1, callback); } public Object navigation(Context context, int requestCode) { return ToolRouter.getInstance().navigation(context, this, requestCode, null); } public Object navigation(Context context, int requestCode, NavigationCallback callback) { return ToolRouter.getInstance().navigation(context, this, requestCode, callback); } }

    五、跳转页面

    调用Postcard的navigation()进行跳转。

    protected Object navigation(Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { try { //准备卡片,路由信息 prepareCard(postcard); } catch (NoRouteFoundException e) { e.printStackTrace(); if (null != callback) { callback.onLost(postcard); } return null; } if (null != callback) { callback.onFound(postcard); } switch (postcard.getType()) { case ACTIVITY: final Context currentContext = null == context ? mContext : context; final Intent intent = new Intent(currentContext, postcard.getDestination()); intent.putExtras(postcard.getExtras()); int flags = postcard.getFlags(); if (-1 != flags) { intent.setFlags(flags); } else if (!(currentContext instanceof Activity)) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } mHandler.post(new Runnable() { @Override public void run() { //带返回码 if(requestCode > 0 ){ ActivityCompat.startActivityForResult((Activity) currentContext,intent,requestCode,postcard.getExtras()); }else { ActivityCompat.startActivity(currentContext,intent,postcard.getExtras()); } if(null != callback){ callback.onArrival(postcard); } } }); break; } return null; }

    先准备路由的卡片信息,如果没有准备路由信息,根据分组名从Warehouse的groupsIndex中找到分组信息类,加载对应路由表的信息。这里实现了按需加载。获取到路由信息后,设置postcard的信息。再调用startActivity来跳转

    private void prepareCard(Postcard postcard) { RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath()); if (null == routeMeta) {//还没有准备信息 //创建并调用 loadinto 函数 然后记录在仓库 Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard .getGroup()); if (null == groupMeta) { throw new NoRouteFoundException("没找到对应路由: " + postcard.getGroup() + " " + postcard.getPath()); } IRouteGroup iGroupInstance = null; try { iGroupInstance = groupMeta.getConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } iGroupInstance.loadInto(Warehouse.routes); //已经准备过了就可以移除了 Warehouse.groupsIndex.remove(postcard.getGroup()); //再次进入else prepareCard(postcard); } else { //获取要跳转的activity postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); // switch (routeMeta.getType()){ // // } } }

    六、使用

    1.在Application中进行初始化

    public class App extends Application { @Override public void onCreate() { super.onCreate(); initToolRouter(); } private void initToolRouter() { ToolRouter.init(this); } }

    2.在FirstActivity 和MainActivity中添加注解,在MainActivity中点击按钮进行跳转

    @Route(path = "/demo1/fisrtActivity") public class FirstActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); } }

     

    @Route(path = "/demo2/MainActivity") public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button jump_btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); jump_btn = findViewById(R.id.jump_btn); jump_btn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.jump_btn: ToolRouter.getInstance().build("/demo1/fisrtActivity") .navigation(); break; } } }

    3.编译期生成的java文件目录如下

    在这里我也分享自己收录整理的Android学习PDF,里面对仿写Arouter框架实现Activity的跳转讲解,希望可以帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,可以分享给身边好友一起学习

    有需要的朋友可以点赞+评论+转发,关注我,然后私信我【666】获取

    也可以加入粉丝群获取:

    Processed: 0.011, SQL: 10