182

Android简易路由框架MobRouter开发 - smallSohoSolo | 博客

 6 years ago
source link: http://smallsoho.com/android/2017/09/22/Android简易路由框架MobRouter开发/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android Router介绍

Android Router即是Android路由工具,通过使用路由工具,可以做到通过一句话进行跳转,无需知道具体的Activity类。

context.startActivity(context,XXX.class); //常见的跳转
MobRouter.build("image_activity").go(); //使用路由框架跳转

通过这种路由跳转的方式,可以做到各个业务模块之间的解耦合。举一个具体的使用场景,我们的模块之间使用了各种AAR的依赖,那么你如果想从一个AAR中跳转到另外一个AAR,那么需要两者有依赖关系才能获取到XXX.class,否则你拿不到类,更不用说跳转了。所以需要一种好的方式来进行解耦合,那么就很需要Router工具。

Router的使用方式

常见的Router使用方式是在一个Activity的类中使用注解标注

@MobRouterPath({"share_activity"})
public class ShareActivity extends Activity {
	//省略代码
}

此处的MobRouterPath标注了这个ShareActivity的名称是什么,之后跳转使用你定义的名称,这里推荐这个名称使用常量来做,能更好的管理名称。

使用MobRouter来进行跳转

MobRouter.build("share_activity")
  .bundle(***) //传入一个bundle
  .with(***) //传入转场动画
  .context(***)  //传入指定的context,默认使用Application
  .XXX //具体的方法可以自行扩展
  .go();

此处可以使用各种扩展方法,比如传入转场动画等,就是对Android Api的封装,此处不赘述。

Router实现细节

Router可以使用两种方式进行跳转

  • 使用反射,通过注解拿到对应的class然后进行跳转
  • 使用APT,在编译时生成map,从map中查到对应的class进行跳转

使用反射的弊端是,反射是及其消耗性能的,Android官方推荐的是尽可能避免反射,使用APT生成代码的方式可以最大化的减少性能损耗,避免每次跳转都用反射来做。所以我们使用APT来做。

这是一个删掉了无用细节的APT类。

@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class MainProcess extends AbstractProcessor {

    private Filer mFiler;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        mFiler = processingEnvironment.getFiler();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
        //...
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(MobRouterPath.class);
      
        for (Element element : elements) {
            MobRouterPath routerPath = element.getAnnotation(MobRouterPath.class);
            for (String key : routerPath.value()) {
                //此处进行map输入
            }
        }
        //...
        javaFile.writeTo(mFiler); //把生成好的文件保存
        return true;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(MobRouterPath.class.getCanonicalName());
        return linkedHashSet;
    }
}

我们可以看到,在编译期间拿到了注解,然后通过注解,使用Javapoet来进行java file 生成,这里产生的对应类为

public class MobRouterPathHolder {
  private static Map sRouterMap = new HashMap<String,Class>();;

  public static Map getRouterMap() {
    sRouterMap.put("image_activity", ImageActivity.class);
    sRouterMap.put("share_activity", ShareActivity.class);
    return sRouterMap;
  }
}

我们可以生成一个静态方法,然后拿到Activity和key的对应的map,从map中读取对应的class进行跳转。

那么如何获取到Map呢?

Class tmp = Class.forName("com.bytedance.mobrouter.MobRouterPathHolder");
            sRouterMap = (Map<String, Class>) tmp.getMethod("getRouterMap", new Class[]{}).invoke(tmp, new Object[]{});

这里使用反射获取到map,这句最好在Application的onCreate中进行,防止还没有注册就进行跳转。此处使用反射一次拿到map之后就不用再使用任何反射了,不会有性能问题。有了map,就可以根据map进行跳转了。

  1. 可以通过对map的修改对跳转进行修改,而且不会有任何兼容性问题
  2. 在众多的插件化框架中,动态加载APK并不会走编译流程,那么可以在下发的APK中加入一个路由表,然后加入到全局的路由map中,就可以实现对下发的插件进行路由而没有任何兼容性问题。

MobRouter是一种思路,具体的更多的业务可以自行发挥,进行更多的开发。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK