ARouter

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43724742/article/details/95904832

使用:

1.添加依赖:

android {
    defaultConfig {
	...
		javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}
dependencies {
    implementation 'com.alibaba:arouter-api:1.5.0'
    annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
    ...
}

2.在Application中初始化:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {	
         	ARouter.openDebug();		//调试模式下必须开启Debug,否则页面无法正常跳转
            ARouter.openLog();
            ARouter.printStackTrace();
        }
        ARouter.init(MyApplication.this);
    }
}

3.在第一个Activity启动时初始化:

protected void onCreate(Bundle savedInstanceState) {
	@Override
    protected void onCreate(Bundle savedInstanceState) {
    	ARouter.getInstance().inject(this);
  	}
}

4.给目标组件类添加注解定义其url:

// 这里的路径是必选项,且这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/testActivity")
public class TestActivity extends AppCompatActivity {
  	 //1.通过Autowired注解表明key 2.需要在onCreate中调用ARouter.getInstance().inject(this);
	 @Autowired(name = "param1")
     public long data;
     //2.通过Autowired注解表明key 2.将param1作为属性的名称 3.需要在onCreate中调用ARouter.getInstance().inject(this);
	 @Autowired()
     public long param1;
     //3.通过Bundle获取
     getIntent().getExtras().getLong("param1")
}

4.跳转:

	//简单跳转
	ARouter.getInstance().build("/test/testActivity").navigation();
	//带参数跳转
	ARouter.getInstance().build("/test/testActivity")
            .withLong("param1", 100L)
            .withString("param2", "mac")
            .withSerializable("param3", new Student("Jack", 18))
            .navigation();

向其他模块传递自定义类型:

@Route(path = "/custom/json")
public class JsonSerializationService implements SerializationService {
    Gson gson;
    @Override
    public <T> T json2Object(String input, Class<T> clazz) {
        return gson.fromJson(input,clazz);
    }
    @Override
    public String object2Json(Object instance) {
        return gson.toJson(instance);
    }
    @Override
    public <T> T parseObject(String input, Type clazz) {
        return gson.fromJson(input,clazz);
    }
    @Override
    public void init(Context context) {
        gson = new Gson();
    }
}

用SerializationService 获取自定义类型

User obj = serializationService.parseObject(getIntent().getStringExtra("key4"), User.class);

其他功能参考官方:
ARouter

源码解析:

定义路由添加路由的接口:

public interface IRouteGroup {
    void loadInto(Map<String, RouteMeta> atlas);
}

public interface IRouteRoot {
    void loadInto(Map<String, Class<? extends IRouteGroup>> routes);
}

用APT在编译期间生成Java类,用来将被Router注解标记的类添加到路由表中:

@AutoService(Processor.class)
@SupportedOptions({KEY_MODULE_NAME, KEY_GENERATE_DOC_NAME})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})
public class RouteProcessor extends AbstractProcessor {
    private Map<String, Set<RouteMeta>> groupMap = new HashMap<>(); // ModuleName and routeMeta.
    private Map<String, String> rootMap = new TreeMap<>();  // Map of root metas, used for generate class file

	@Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (!Utils.isEmpty(set)) {
            //被Route注解的节点集合
            Set<? extends Element> rootElements = roundEnvironment.getElementsAnnotatedWith(Route.class);
            if (!Utils.isEmpty(rootElements)) {
            	//遍历rootElements,生成java文件,略;
                processorRoute(rootElements);
            }
            return true;
        }
        return false;
    }
}

生成的java文件形如:

//把某个分组放入路由表中
public class ARouter_Root_app implements IRouteRoot {
  @Override
  public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
    routes.put("main", EaseRouter_Group_main.class);
    routes.put("show", EaseRouter_Group_show.class);
  }
}

//把某个分组下的类放如路由表中
public class ARouter_Group_main implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/main/main",RouteMeta.build(RouteMeta.Type.ACTIVITY,Main2\Activity.class,"/main/main","main"));
    atlas.put("/main/main2",RouteMeta.build(RouteMeta.Type.ACTIVITY,Main2\Activity.class,"/main/main2","main"));
  }
}

在创建Application的时候需要初始化路由表:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        ARouter.init(this);
    }
}

ARouter的初始化做了以下工作:

private static void loadInfo() throws PackageManager.NameNotFoundException, InterruptedException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    //获得所有APT生成的路由类的类名
    Set<String> routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
    for (String className : routerMap) {
        if (className.startsWith(ROUTE_ROOT_PAKCAGE + "." + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
           	//这里只会把一级目录(也就是Group)放入Warehouse的组路由表中
            ((IRouteRoot) Class.forName(className).getConstructor().newInstance()).loadInto(Warehouse.groupsIndex);
        }
    }
}

ClassUtils类获取全部路由类的过程,这里开启了新的线程扫描整个APK中所有的类,找到特定的类名返回;

 public static Set<String> getFileNameByPackageName(Application context, final String packageName)
            throws PackageManager.NameNotFoundException, InterruptedException {
        final Set<String> classNames = new HashSet<>();
        //获得所有APK的路径
        List<String> paths = getSourcePaths(context);
        //使用同步计数器判断均处理完成
        final CountDownLatch countDownLatch = new CountDownLatch(paths.size());
        ThreadPoolExecutor threadPoolExecutor = DefaultPoolExecutor.newDefaultPoolExecutor(paths.size());
        for (final String path : paths) {			//遍历每个APK
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    DexFile dexFile = null;
                    try {
                        //加载 apk中的dex 并遍历 获得所有包名为 {packageName} 的类
                        dexFile = new DexFile(path);
                        Enumeration<String> dexEntries = dexFile.entries();
                        while (dexEntries.hasMoreElements()) {
                            String className = dexEntries.nextElement();
                            //找到前缀为特定字符串的类名,因为APT生成的类都会以这个前缀命名,
                            //所以这里找到的是所有处理Router注解的APT生成的类的全名
                            if (!TextUtils.isEmpty(className) && className.startsWith(packageName)) {
                                classNames.add(className);
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            });
        }
        //等待执行完成
        countDownLatch.await();
        return classNames;
    }

看看管理路由表的类

class Warehouse {
    // Cache route and metas
    //初始化完成之后或填充这个Map
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    static Map<String, RouteMeta> routes = new HashMap<>();

    // Cache provider
    static Map<Class, IProvider> providers = new HashMap<>();
    static Map<String, RouteMeta> providersIndex = new HashMap<>();

    // Cache interceptor
    static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
    static List<IInterceptor> interceptors = new ArrayList<>();

    static void clear() {
        routes.clear();
        groupsIndex.clear();
        providers.clear();
        providersIndex.clear();
        interceptors.clear();
        interceptorsIndex.clear();
    }
}

页面跳转的过程:

	ARouter.getsInstance().build("/module1/module1main").navigation();

这里build方法返回的是一个PostCard对象:

public class Postcard extends RouteMeta {
    private Bundle mBundle;
    private int flags = -1;
    private Bundle optionsCompat;
    private int enterAnim;
    private int exitAnim;
	protected Object navigation(Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
	//准备Postcard中的参数
	prepareCard(postcard);
 	switch (postcard.getType()) {
        case ACTIVITY:
        	//根据PostCard中的参数构建Intent,并启动Activity
            final Context currentContext = null == context ? mContext : context;
            final Intent intent = new Intent(currentContext, postcard.getDestination());
            intent.putExtras(postcard.getExtras());
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    //可能需要返回码
                    if (requestCode > 0) {
                        ActivityCompat.startActivityForResult((Activity) currentContext, intent,
                                requestCode, postcard.getOptionsBundle());
                    } else {
                        ActivityCompat.startActivity(currentContext, intent, postcard
                                .getOptionsBundle());
                    }
                    //跳转完成
                    if (null != callback) {
                        callback.onArrival(postcard);
                    }
                }
            });
            break;
        default:
            break;
    	}
    	return null;
	}
	
	private void prepareCard(Postcard card) {
		//从路由表中获取Activity类信息
    	RouteMeta routeMeta = Warehouse.routes.get(card.getPath());
    	//初始化时为了节省性能,只会加载所有的分组信息,而每个分组下的路由映射关系,会使用懒加载,在首次用到的时候去加载
    	if (null == routeMeta) {
    		//获取url对应的Group
        	Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(card.getGroup());
        	IRouteGroup iGroupInstance;
        	//创建一个IRouteGroup对象
            iGroupInstance = groupMeta.getConstructor().newInstance();
        	iGroupInstance.loadInto(Warehouse.routes);
        	Warehouse.groupsIndex.remove(card.getGroup());
        	//再次执行会进入else分支
        	prepareCard(card);
    	} else {
        	//将RouteMeta里面保存的activityClass放入Postcard里面
        	card.setDestination(routeMeta.getDestination());
        	card.setType(routeMeta.getType());
        	switch (routeMeta.getType()) {
            	case ISERVICE:
                	Class<?> destination = routeMeta.getDestination();
                	IService service = Warehouse.services.get(destination);
                	if (null == service) {
                    	try {
                        	service = (IService) destination.getConstructor().newInstance();
                        	Warehouse.services.put(destination, service);
                    	} catch (Exception e) {
                        	e.printStackTrace();
                    	}
                	}
                	card.setService(service);
                	break;
            	default:
                	break;
        	}
    	}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43724742/article/details/95904832