版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
使用:
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;
}
}
}
}