ARouter

1.使用:

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

2.源码解析:

1.ARouter初始化过程:

Application初始化时要初始化ARouter:

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

ARouter初始化的过程:

public final class ARouter {
	private volatile static _ARouter instance = null;
	private static Handler mHandler;
	private volatile static boolean hasInit = false;

	protected static _ARouter getInstance() {
		...
		return instance;
	}
	
	public static void init(Application application) {
		if (!hasInit) {
			 mContext = application;
        	 LogisticsCenter.init(mContext, executor);
       	 	 hasInit = true;
       	 	 mHandler = new Handler(Looper.getMainLooper());
		}
	}
}

LogisticsCenter初始化:

//className = LogisticsCenter 
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
	Set<String> routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
    for (String className : routerMap) {
    	//className以com.alibaba.android.arouter.routes.ARouter$$Root开头
        if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
           	//这里只会把一级目录(也就是Group)放入Warehouse的组路由表中
            ((IRouteRoot) (Class.forName(className).getConstructor()
            		.newInstance())).loadInto(Warehouse.groupsIndex);
        }
        //className以com.alibaba.android.arouter.routes.ARouter$$Interceptors开头
        else if(className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
            ((IInterceptorGroup) (Class.forName(className).getConstructor()
                    .newInstance())).loadInto(Warehouse.interceptorsIndex);
        }
        //className以com.alibaba.android.arouter.routes.ARouter$$Providers开头
        else if(className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
            ((IProviderGroup) (Class.forName(className).getConstructor()
                    .newInstance())).loadInto(Warehouse.providersIndex);
        }
    }
}

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

 //扫描所有APK,把包名为packageName的所有类的类名添加到Set并返回
 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;
    }

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

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"));
  	}
}

管理路由表的类Warehouse

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初始化会全局搜索@Route注解,这些带有@Router注解的类会通过APT生成Java文件,初始化的过程中会创建这些类的实例,执行这些类的方法就会填充Warehouse中的路由表

2.页面跳转的过程:
	ARouter.getsInstance().build("/module1/module1main").navigation();

这里build方法返回的是一个PostCard对象,PostCard又是RouteMeta的子类:

public class RouteMeta {
    private RouteType type;         	//当前路径对应的类型,如Activity
    private Element rawType;        
    private Class<?> destination;   	//用destination就可以创建想要的类
    private String path;            
    private String group;        
    private int priority = -1;     
    private int extra;              
    private Map<String, Integer> paramsType;  
    private String name;
    private Map<String, Autowired> injectConfig;    
}
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;
	}
	//这个方法就是把Warehouse中某路径对应的RouteMeta的关键信息赋值给Postcard 
	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;
        	}
    	}
	}
}

总结:
跳转的过程就是根据Url查询路由表,用路由表中的信息初始化一个构造一个PostCard,然后通过PostCard构造一个Intent开启Activity

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值