Arouter从使用到原理

这是我参加8月更文应战的第2天,活动概略检查:8月更文应战

前语

但凡A,B无依托联络,且想要彼此通讯的,其最基本的原理便是经过一个彼此都依托的第三方C,不管是binder,socket,file,provider仍是EventBuAPPs,Arouter等,都是这个原理,假定有人说不,那么要么是杠精,要么是想引人留心,要么便是扔掉了医治。

咱们假定现有: app,login,以及common三个module,其间app跟login无关联,而且都依托于common,其间app modul变量名的命名规矩e中有个MainActivity,login module想要调用MainActivity,依据Kotlin上述,只能经过一起依托的common 或 其他公有依托来完结。

1 经过common来完approve

  • 1 在common中界说一个Map<String,Class<? extends Activity>&线程池原理gt;
  • 2 在app module中,将M缓存视频怎样下载到手机相册ainActivity.cl缓存视频兼并app下载ass增加到这个map中去:
map.pu线程池的运用t("main",MainActivity.class)
  • 3 在l缓存视频怎样转入本地视频ogin module中,经过map.get(“main”)得到MainA缓存的视频怎样保存到本地ctivity.class,然后创立变量名的命名规矩Intent来建议MainActivity
Class<? extends Activity> mainActivityClass= map.get("main")缓存视频兼并app下载
startActivity缓存视频兼并app下载(new Intent(this,mainActivityClass))

中心就两点: 注入获取。说白了便是: 你把自己想让appearance他人用的放进公共库房中(注入),并供应一个凭据(这儿的凭据便是kotlin下载字符串”main”缓存数据能够铲除吗),也便是key,我想要的时分就拿着凭据从公共仓apple库中取出来(获取),公共库房便是彼此缓存数据能够铲除吗都能拜访的,那肯定是彼此都依托的。

接着,咱们来看Arouter的完结。

2 经过Arouter来完结。

经过Arou缓存视频在手机哪里找ter的完结思路跟上述是相同的,只不过Arouter更简略,更省事,更”愚人”,它appear把咱们的”注入”和”获取”都完结了(开发把自己当痴人调API就行了),而且还加了许多优化,可是道理都是相同的,咱们来看下。

简略运用

1 在gradle文件增加依托:

假定是java则缓存增加:

api 'com.alibaba:arouter-api:1.5.0'
annotationProcessor 'com.alibaba:线程池品种arouter变量之间的联系-compile线程池作业原理r:1.2.2'
android {
d变量和常量的差异efaultConf变量泵ig {
javaCompileOptions {
annotationProcapplicationessorOptions {
arguments = [ARapproachOUTER_MODULE_NAME: project.getName()]
}
}
}
}

假定是kotlin,则增加:

api 'com.alibaba:arouter-applicationapi:1.5.0'
kapt 'com.alibaba:arouter-compiler:1.2.2'
android {
defaultConfig {
kapt {
arguments {
arg("AROUTER_MODULE_NAME", projectappreciate.getName())
}
}
}
}

java和kotlin的差异apple,便是kotlin运用kapt关键字,别的都相同。

2 在Application的onCreate()里边初始化

// 初始化(注入)
ARouter.init(this);

3 界说path变量英文,也便是凭据

@Route(path = "/app/activity_main") // 这个kotlin言语便是凭据,也便是key
public clas线程池面试题s Mkotlin和javaainActivity {}

4 依据path线程池原理建议对应的Activity,也便是获取

ARouter.getInstance().build(path变量英文).navigation(); // 依据凭据path获取并建议Activity

线程池参数设置准则间ARouterapp是什么意思.init(this)便是注入的进程,注入的key便是咱们经过@Route(path)界说的path;然后就拿着path去调用navigation()来获取并建议对应的Activit缓存数据能够铲除吗y了。

上面仅仅简略示例Arouter的运用,不过多介绍,本篇关键是解说原理。想看具体运用能够拜访: Arouter官网。

那么,Arouter的注入是怎样做的呢,获取又是怎样kotlin下载获取的呢,且看下文。变量是什么意思

原理剖析

1 编译时干的变量的界说事 – 生成中间代码

apt技能: a变量是什么意思pt技能便是 先设定一套代码模版,然后在类加载期间,动态appointment依据指定的代码模版生成一个.java文件,这个文件在运转时能够直接拜访,能够看这儿加深了解。

如下图:

Arouter从运用到原理

所以,当咱们在gralde中增加了Arouter的依托后kotlin高阶函数,那么在编译时就会缓存 在对应module的 /applicationbuild/ge变量泵nerated/source/kapt/deb变量ug/ 下生成 “com.alibaba.android.aroutappstoreer.routes” 目录,Arouter生成的代码都放在这儿,比线程池回绝战略如:

// 这一个IappointmentRouteRoot,看姓名"ARouter$$Root$$app",其间"ARouter$$Root"是前缀,"app"是group姓名kotlin教程,也便是path里边以"/"分隔得到的第一个字符串,然后通线程池回绝战略过"$$"连接,
// 那么这玩意儿的无缺类名线程池的创立办法有几种便是"com.alibaappointmentba.android.arouter.routes.ARouter$$Root$kotlin高阶函数$app"
public class ARouter$$Root$$app implements IRouteRoot {
// 参数是一个map,value类型是 IRouteGroup
@Override
papproveublic void变量是什么意思 loadInto(Map<String, Class<? extends IRouteGroup>&变量与函数gt; routes) {
// "app"便是@Route(path = "/app/activity_main") 中的"app",在Arouter中叫做group,是以path中的"/"分隔得到的
// 这个的value是:ARouter$$Gr线程池的创立办法有几种oup$$app.class,也便是下面的类
routes.put("app", ARouter$$Grouappreciatep$$app.classkotlin言语);
}
}
// 这是一个IRouteGroup,同理,前缀是缓存视频怎样转入相册"ARouter$$Group"
public class ARo变量类型有哪些uter$$Group$$app变量 implements IRouteGroup {
@Overridekotlin教程
public void loadInto(Map<String, RouteMeta> atlas) {
// "app/activity缓存数据能够铲除吗_main"便是咱们经过@Route指定线程池面试题的path,后边RouteMeta保存了要建议的组件类型,以及对应的.class文件
// 这个 RouteMeta.build()的参数很重要,后边要用到
atl缓存的视频怎样保存到本地as.put("/app/activity_main", RouteMeta.build(Rou变量与函数teType.ACTIVITY, MainActivkotlin下载ity.cla变量名的命名规矩ss, "/app/activity_main", "app", null, -1, -2147483648));
}
}
// RouteMeta.build()办法,参数后边有用
// type便是: RouteType.ACTIVITY,
// destination便是MainActivity.class,
// path便是"/app/act变量名的命名规矩ivity_main",
// group便是"app"
// paramsType是null
// priority是-1
// extra是-2147483648
public static RouteMeta build(RouteType缓存 type, Class<?> destination, String path, String group, Map<String, Integer> paramsType, int priority, int extra) {
return new RouteMeta(type, nu线程池参数设置准则ll, dapproveestination, null, path, group, paramkotlin实战sType, priori缓存ty, extra);
}

留心,上述代码悉数缓存视频怎样转入本地视频是在app module中的build()中线程池品种生成appstore的。也便是说,这些kotlin实战代码关于login module来说,是完全透明的,不可达的。

而且,咱们发现生成的.jav缓存视频变成本地视频a文件,都有个一起的前缀”ARouter缓存$$”,比方”ARouter$$Root”。又因为它们是在Arouter缓存视频怎样转入相册生成的目录下面,所以它们的无缺类名都有个前缀:“com.缓存视频变成本地视频alibaba.android.arouter.routes.ARouter$$”。好,现在假定编译完了,咱们建议app。

2 运转时变量类型有哪些干的事 – 注入

现在咱们现已编译完了,直接点击run建议了app,现在来到了运转kotlin教程时,此刻咱们现已在/builkotlin和javad/generated/source/kapt/debug/ 下生成了 “com.alibaba.android.kotlin实战arouter.routes”目录,而且里边还有一堆Arouter生成的代码。

接下来代码次第实施,跑到了Application的onCreate()里边,所以就实施了初始化:

// 初始化,此刻会调用编译时生成的那一堆代码,来"注入"需求的相关信息
Arouter.init(this)
// 调到了这儿
protected static synchronized boolean init(Application application) {
// 保存了mCoKotlinntext,后边有用
mContext = application;
// 初始化
LogisticsCente缓存视频怎样转入相册r.init(mContext, executor);
hasInit = true;
mHandler = nAPPew Handler(Looper.getMainLooper());
return true;
}

咱们跟着代码,发kotlin怎样读现究竟调了:

// execukotlin协程原理tor是内置的一个线程池
LogisticsCenter.init(m线程池创立的四种Context, executor);

接下来咱们就来看这个代码,这儿删除了日志以及部分非有必要逻辑:

public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = conteapp是什么意思xt;
executor = tpe;
trappreciatey {
Set<String> routerMap;
// 假定是debugable缓存视频兼并()或许更新了app的版别
if (ARou线程池品种ter.debuggable() || PackageUtils.isNewVersion(context)) {
// 那么就会从头获取悉数的class,所以,当你的Arouter出现了route not found时分,更新版别号 或许 翻开Arouter的debug就ok了缓存视频变成本地视频。
// 这儿会获取悉数"com.alibaba.android.arouter.routes"目录下kotlin和java的class文件的类名。
routerMap = ClassUtils.getFileNameByPappleackageName(mContext, ROUTE_ROOT_PAKCAGE);
// 这儿缓存到SharedPrefereappearnces里边,便利下次获取。
if (!routerMap.isEmpty()) {
context.getSharedPreferences(AROUTER_SP_CAappearanceCHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_变量之间的联系KEY_MAP, routerMap).apply();kotlin面试题
}
// 将app的版别号缓存到SharedPreferences,便利变量类型有哪些下次运用。
PackageUtils.updateVersion(context);
} else {
// 假定版别号没有更新,而且没翻开debug,则从缓存中取出之前缓存的悉数class
rappearouterMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE线程池).getStringSet(AROUTER_SP_KEY_MAP, new HashSet&l缓存数据能够铲除吗t;String>()));
}
// 遍历刚刚拿到的悉数类名,而且反射调用它们的loadInto()办法,那apple么app module中的那些生成的类,它们的loadinto()kotlin下载就被调用了,而且注入到参数里边了。
for (String className : routerMap) {
// 拼接的字符串其实便是"com.alibaba.android.arouter.routes.ARouter$$Root",这不便是编译时生成的那个"ARouter$$Root$$app"的前缀吗。
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_kotlin言语NAME + S缓存视频怎样下载到手机相册EPARATOR + SUFFIX_ROOT)) {
// 所以,调用了它的loadIn变量之间的联系to(map),也就等appointment价于调用了:map.put("app", ARouter$$Group$$app.缓存的视频怎样保存到本地class),这个键值对 就放在了Warehouse.groupsIndex里边。
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
// 这缓存视频在手机哪里找个是"com.alibaba.android.aro变量泵uter.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);
// 这个是"com.alibaba.android.arouter.routes.ARouter$$Providers"
} else if (classNa缓存视频兼并app下载me.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
((IProviderGroup) (Class.forName(className).gKotlinetConstruckotlin教程tor().newInstance())).load线程池品种Into(Warehouse.providersIndex);
}
}
} cakotlin面试题tch (Exception e) {
throw new HandlerExceappleption(TAG + "ARouter init logistics cen线程池作业原理ter exception! [" + e.getMessage() + "]");
}
}

依据上述,咱们知道:

  • 1 获取悉数”com.alibaba.android.arouter.routes”目录下的类名,这一步有个缓存操作变量类型有哪些
  • 2 遍历悉数获取到的类名,然后调用它们的loadI线程池面试题nto(map)办法。
  • 3 调用loadInto(map)的效果便是将多有的(key,group.class)类存入Warehouse.groupsIndex里边

咱们看下Warehoukotlin教程se的代码:

class Warehouse {
// Cache route and metas
// 这个便是咱们刚刚注入的那个map,公开接纳一个IRou线程池面试题teGroup,对上了。
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
statikotlin实战c Mkotlin言语ap<String, RouteMeta> routekotlin高阶函数s = new HashMap<>();
// Cache provider
static Map<Class, IProvikotlin下载der> providers = new Hash缓存视频兼并Map<>();
static Map<String, RouteMeta> providersIndex = new HashMap<>();
// Cache i变量英文ntercepto变量是什么意思r
static Map<Integer, Class<? exteappstorends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than o变量英文ne interceptors use same priority [%缓存视频怎样转入相册s]kotlin言语");
static List<IInterceptor> interceptors = new ArrayList<>();
statickotlin和java void clear() {
routes.clea变量类型有哪些r();
groupsIndex.clear();
providers.clear();
prokotlin和javavidersIndex.clear();
interceptors.clear();
interceptorsIndex.clear();
}
}

接下来咱们看下获取悉数”com.alibaba.android.arouter.kotlin言语routes”目录下线程池原理的class文件途径apple的逻辑,关键!

// 我缓存数据能够铲除吗们传进来的packageName是 "com.alibaba.android.arouter.routes"
public static Set<String> getFileNameByPackageName(Context context, final String packageName) throws PackageManager.NameNotFoundException, IOException, Int变量和常量的差异erruptedExcept线程池回绝战略ion {
final Set&线程池的七个参数l缓存视频怎样下载到手机相册t;String> classNames = new HashSet<>();线程池回绝战略
// 获取悉数dex文件的途径,关键,下面有
List<String> p变量和常量的差异aths = getSourcePaths(context);
final CountDownLatch parserCtl = new CountDownLatch(paths.size());
/变量的界说/ 遍历悉数dex文件的途径
for (变量final String path : paths) {
DefaultPoolExecutor.getInstance().execute(new Runnable() {
@Override
public void run() {
DexFile dexfile = null;
try {
// 是否是".zip"文件
if (path.endsWithappreciate(EXTRACTE变量是什么意思D_SUFFIX)) {
// 假定是.zip文件,就调用loadDex来加载
dexfile = DexFi缓存是什么意思le.loadDex(path, path + ".tmp", 0);
} else {
// 不然,直接依据途径创立即可kotlin言语
dexfile = new DexFile(path);
}
//变量的界说 遍历dexfile下面的元素
En缓存视频怎样转入本地视频umerakotlin怎样读tion<String> dexEntries = dexfile.entries();
while (dexEntries.ha线程池面试题sMoreElements()) {
Sappreciatetring className = dexEntries.nextElement();
// 假定是以"com.缓存视频怎样下载到手机相册alibaba.android.arouter.routes"初步,就增加
if (className.starts缓存的视频怎样保存到本地With(packageName)) {
classNames.add(className);
}
}
} catch (Throwable ignore) {
Log.e("ARouter", "Scan map file in dex files made error.", ignore);
} finally {
if (null != dexfile) {
try {
dexfile.close();
} catch (kotlin言语Throwable ignore) {
}
}
parserCtl.countDown();
}
}
});缓存
}
parserCtl.await();
// 回来
return classNames;
}

上面代码的逻辑很简略:

  • 1 获取悉数Dex文件途径,而且遍缓存视频怎样转入相册历创立DexFile
  • 2 遍历DexFile,而且将悉数以”com.alibaba.android.arouter.routes”文件初步的增加,然后回来。

依据上面章节,咱们又知道,ARouter在编译时生成的文件都是以”com.alibaba.android.arouter.routes”为前缀的,所以这个函数的效果便是获取悉数Arouter编译时生成的文件名。

然后咱们来看,缓存视频变成本地视频怎样获取悉数DexFile文件途径:

public static List<String> getSourcePaths(Conapprovetextapproach context) throws PackageManager.NameNotFoundException, IOException {
ApplicationInfo a缓存pplic变量类型有哪些ati线程池作业原理onInfo = context.getPackageManager().getApplicationInfoappreciate(context.g线程池的运用etPackageName(), 0);
File sourceApk = new File(applicationInfo.sourceDir);
List<String> sourcePaths = new ArrayList<>();
// 增加apk的默许途径,能够理解为apk文件的途径
sourcePaths.add(applicationInfo.sourAPPceDir);
// EXTRACTED_NAME_EXT 便是 ".classes",所以这个效果相似缓存视频变成本地视频于 "test.classes"这样
String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;
// 假定翻开了MultiDex,那么就遍历获取每一个dex文件的途径
if (!isVMMultidexCapable()) {
// 获取悉数Dex文件的总数
int totalDexNumber = getMultiDexPreferences(context).getInt(KEY_DEX_NUMBER, 1);
File缓存视频兼并 dex变量与函数Dir = new File(applicationInfo.dataDir, SECONDARY_FOLDER变量的界说_NAME);
// 遍历获取途径
for (int secondaryNumber = 2变量泵; secondaryNumber <= totalDexNumber; secon变量与函数daryNumber++) {
//EXTRACTED_SUFFIX 便是 ".zip",所以fileName就相似于 test.classes2.zip,kotlin协程原理 test.classes3.缓存是什么意思zip这样
String filkotlin面试题eName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX;
File extractedFile = new File(dexDir, fileName);
if (extr缓存actedFile.isFile(approach)) {
// 增加途径
sourcePapplicationakotlin言语ths.add(extractedFile.getAbsolutePath());
} else {
throw new IOExcept变量ion("Missing extracte变量名的命名规矩d secondary dex file '" + extract缓存视频变成本地视频edFile.getPath() + "'");
}
}
}
// 回来线程池的七个参数
return sourcePaths;
}

上述代码的逻辑很简略,便是获取app对应kotlin面试题的悉数的Dex文件的途径,其实Android的代码打包出来便是一堆Dex文件,能够看成是.class文件的合集。kotlin为什么盛行不起来也便是说,咱们写代码到打包的时分,是:.javaappstore -> .class -&缓存是什么意思gt; .dex这样的包装,而现在,咱们要反过来,从 .dex -> .class这样搞回去,当然咱们只需求得到.class就足矣。

好,咱们再来回想一下流程:

  • 1 在Application的onCreate()里边咱们调用了Arouter.init(this)。
  • 2 接着调用了ClassUtils.getFileNameByPackageNam()来获appearance取悉数”com.alibaba.android.arouter.routes”目录下的dex文件的途径。
  • 3 然后遍历这些dex文件获取悉数的calss文件的无缺类名appearance
  • 4 然后遍历悉数类名,获取线程池的七个参数指定前缀的类,然后经过反射调用它们的loadInto(map)办法,这是个注入的进程,都线程池的运用注入到参数Warehouse的成员变量里边了。
  • 5 其间就有Arouter变量类型有哪些在编译时生成的”com.alibaba.android.arouter.routes.ARouter$$Root.ARouter$$Root$$app”类,它对应的代码:<“app”, ARouter$$Group$$app.class>就被增加到Warehouse.groupsIndex里边了。

好,现在咱们的注入进程就完事了,说白了便是:变量名的命名规矩 app包名 -> 获取.dex -> 获取.class -> 找对应的.class -> 反射调用办法变量泵 -> 存入Warehouse中,这个进程便是注入,Warehouse便是库房,里边保存了需求的key和.class,好,咱们来看获取的进程

3 调用时干的事 – 获取

调用的代码很简略:

// 这儿的path便是咱们经过@Route指定的,也便是"/ap线程池创立的四种p/activity_main"
ARout线程池面试题er.getInstance().build(p线程池创立的四种ath).navigation();

其间Arouter.getInstance()很kotlin教程简略,便是个单例,我看看build(path)函数:

public Postcard build(String path) {
// 就一行代码
retu线程池参数设置准则rn _ARouter.getInstance().build(path);
}
// 调到了这儿
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throkotlin高阶函数w new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
//...省掉一些代码
// 到这儿,extractGroup(path)是获取group姓名的,pa缓存视频怎样下载到手机相册th是"/app/activity_main",那么group便是app
return build(path, extractGroup(path));
}
}
// 获取group姓名,参数便是"/app/activity_main"
private Strinapproachg extractGro变量min表明什么类型的变量up(String path) {
// 校验path的合法性,比方:假定不是以"/"初步,就报错
if (TextUtils.isEmpty(path) || !path.stakotlin高阶函数rtsWith("/")) {
throw new HandlerException(appreciateConsts.变量和常量的差异TAG + "Extra线程池品种ct the defaultkotlin实战 gkotlin怎样读roup failed, the path must be start with '/' and contain more than 2 '/'!");
}
try {
// 获取group姓名,效果便是"apkotlin和javap"approach
String defaultGroup = path.substring(1, path.indexOf("/", 1)线程池原理);
if (TextUtils.isEmpty(defaultGroup)) {
throw new HandlerException(Consts.TAG + "Extract the default group failed! There's nothing between 2 '/'!");
} else {
return defaapp是什么意思ultGroup;
}
} catch (Exception e) {
logger.wa变量名的命名规矩rning(Consts.TAG, "Failed to extract default group! " + e.getMessage());
return nullkotlin为什么盛行不起来;
}
}
// 接着走build,咱们现已知道参数是("/app/activity_main","app")了
prokotlin怎样读tected Postcard buapproachild(String path, String group) {
if (TextUtils.iskotlin高阶函数Empty(path) || TextUtil线程池面试题s.isEmpty(group)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
// ... 省掉一些代码
// 直接创立了个玩意,咱们就叫它明信片吧
rappleeturn new Postcard(path, group);
}
}
// 来看下明信片的结构
public Postcard(String path, String group) {
// 调下面
this(path, group, null, null);
}
// 究竟走到这儿
puAPPblic Postcard(String path, String group, Uri uri, Bundle bundle) {
// 保appointment存了path,便是"/app/activiapplicationty_main"
setPath(paapproveth);
// 保存了group,便是"app"
setGroup(group);
// uri是null !!!
setUri(uri);
// 创立了个B缓存的视频怎样保存到本地undle线程池的运用()
this.mBundle =线程池品种 (null == bundle ? new Bundle() : bundle);
}

好,完事,现在咱们知道,ARouter.getInstance().build(path);究竟是创立了个Postcard,保存了pa变量名的命名规矩th和group,然后咱们看下Postcard的navigation()函数:

public Obj缓存视频怎样转入本地视频ect navigation() {
// 这儿的参缓存视频怎样转入相册数传个null
return navigation(null);
}
// 参数是null
public O变量类型有哪些bject navigaappearancetion(Context context) {
//变量名的命名规矩 重载调用,这个context是null
return naviga变量min表明什么类型的变量t线程池的七个参数ion(contekotlin实战xt, null)线程池品种;
}
// 经过一番变量类型有哪些线程池的运用用,究竟走到这儿
public Object navigation(Context context变量的界说, NavigationCallback callback) {
// 这儿缓存视频怎样转入本地视频将this作为参数调用下去,this线程池创立的四种便是Postcard,包变量的界说含了刚刚的path和group。
return ARouter.getInstance().navigation(context, this, -1, callback);
}
// 来到了这儿
pu缓存视频在手机哪里找blic Object navigation(Context mContext, Postc变量min表明什么类型的变量ard postcard, int requestC线程池回绝战略ode, NavigationCallback callback) {
// 又是个甩锅函数
return _A变量类型有哪些Router.getInstance().nav缓存数据能够铲除吗igationapple(mContext, pos变量之间的联系tcard, requestCodekotlin协程原理, callback);
}
// 接着来approach到了这儿
protected Object navigation(f变量与函数inal Context context, fina变量之间的联系l Poskotlin教程tcard postcard, finkotlin面试题al i变量和常量的差异nt rappstoreequestCode, final Na变量英文vigationCallback callback) {
//...
try {
// 中心函数1
LogisticsCenter.completi缓存视频在手机哪里找on(postcard);
} catch (NoRouteFo变量的界说undExceptikotlin协程原理on ex) {
if (null != callback) {变量
callb缓存视频兼并ack.onLost(postcard);
} else {
DegradeService deappearancegrakotlin下载deService = ARouter.getInstance().navigation(DegradeService.class);APP
if (null != degradeServicappearancee) {
degra缓存视频在手机哪里找deService.onLost(context, postcard)kotlin教程;
}
}
return null;
}
if (null != callback) {
callback.onFound(postc线程池品种ard);
}
// 判断是否需求调用拦截器
if (!postcard.ikotlin协程原理sGreenChannel()) {
// 需求调用appearance拦截器
interceptorService.doI变量min表明什么类型的变量nterceptions(postcard, new InterceptorCallback()线程池品种 {
@Override
public void onContinue(Postcard postcard) {
_navi线程池原理gation(context, poappointmentstcard, requestCkotlin实战ode, callback);
}
@Override
publi缓存视频怎样下载到手机相册c void onInterrupt(Throwable excekotlin实战ption) {
if (null != callback) {
callback.onInterrupt(postcard);
}
logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {
// 不需求调用拦截器
// 中心函数2
return _navigation(context, postcard, requestCode, callback);
}
return null;
}

变量min表明什么类型的变量着,咱们来看那两个中心函数:

// 中心函数1
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");kotlin实战
}
// 先从Warehouse.routes里边获取RouteMeta,咱们上述代码的经历只用到了Warehouse.groupsIndex,缓存视频在手机哪里找所以肯定是null
// 第2次过来了,现在Warehouse.routes有值了,便是依据path拿到的。
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
// 接着跑这儿,从Warehou线程池se.groupsIndex获取IRo缓存视频在手机哪里找uteGroup的class!终于用到咱们前面注入的玩意线程池的七个参数变量是什么意思了,postcard.getGroup()便是"app",
// 而咱们前面调过 Warehouse.groupsIndex.put("app", ARouter$$Group$$app.class),这儿就直接取出来了。
Class<? extends IRout缓存数据能够铲除吗eGroup> groupMeta = Wareh线程池oukotlin怎样读se.groupsIndex.get(postcard.getGroup());
if (null == groupMeta) {
throw neapplew NoRouteFoundEx线程池回绝战略ception(TAG + "The变量泵re is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
try {
//缓存视频兼并app下载 初步反射了
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
// 调了loadInfo,咱们回去看下ARouter$$Group$$app.缓存视频怎样下载到手机相册class的loa线程池创立的四种dInto办法:
// atlas.put("/app/activity_main", Rkotlin高阶函数outeMeta.build(RouteType.ACTIVITY, MainActivity.ckotlin高阶函数lass, "/app/activity_main", "app", null, -1, -2147483648));
// 直接put了,kappearanceey是"/app/activity_main",跟Postcard的path相同,这下就放在Wareh线程池参数设置准则ouse.routes里边了,下次就能拿到了。
iGroupInstance.loadInto(缓存视频怎样转入相册Warehouse.routes);
// 把group丢掉,group的意义便是用来拿routekotlin面试题的,现在拿到了现已没用了,删除省内存。
Warehouse.groupsIndex.remove(postcard.getGroup());
} catch (Exception e) {
thr线程池的创立办法有几种ow new HaappstorendlerException(TAG + "Fatal exception when loading group meta. [" + e.g缓存视频怎样转入本地视频etMessage() +线程池的七个参数 "]");
}
// 又调了自己,回到这个函数头从头看
com变量之间的联系pletion(postcard);
}
} else {
// 第2次进来,跑这儿,设置一堆特点,还记得很重要的那一堆参数吗
// RouteMeta.build(RouteType.ACTIVITY, MainActivkotlin协程原理ity.claskotlin教程s, "/app/activity_main", "ap缓存视频怎样转入本地视频p", null, -1, -21474缓存视频怎样转入本地视频83648)
postcard.setDestination(routeMeta.geAPPtDestination()); // MainActivity.class
postcard.setType(routeMetaappearance.getType()); // RouteT变量英文ype.ACTIVITY
postcard.setPriority(routeMeta.getPriority()); // -1
postcard.setExtra(routeMeta.getExtra变量英文()); // -2147483648
// uri是null,不必看
Uri rawUri = postcapplicationard.getUri();
if (null != rawUri) {   // T缓存视频兼并ry to set para线程池创立的四种ms into bundle.
Map&lt缓存数据能够铲除吗;String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
Map<Strin缓存视频怎样下载到手机相册g, Integer> paramsType = routeMekotlin怎样读ta.getParamsType();
if (MapUt线程池的创立办法有几种ils.isNotEmpty(paramsType)) {
for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
setValue(postcard,
par变量和常量的差异ams.getValue(),
params.getK变量泵ey(),
resultMap.get缓存视频在手机哪里找(params.getKey()));
}
postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArra变量的界说y(new String[]{}));
}
postcard.withString(ARouter.Rkotlin教程AW_URI, rawUri.toString());
}
// 根apple据类型实施逻辑,咱们的类型是RouteType.ACTIVITY,下面好像都没有
switch (routeMeta.getType()) {
case PROVIDER:
Class<? extends IProvider变量和常量的差异> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = W变量arehouse.providers.get(providerMeta);
if (null == ikotlin高阶函数nstance) { // There's no instance of this provider
IProvider provider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.pro线程池创立的四种viders.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}线程池品种
postcard.setProvider(i缓存视频兼并app下载nstance);
postcard.greenChannel();
break;
cas变量类型有哪些e FRAGMENT:
postcard.greenChann缓存视频怎样转入相册el();
defauapprovelt:线程池回绝战略
break;
}
}
}

中心函数1搞完了,总共跑了两次,

  • 第一次,咱们从Warehouse.groupsIndex取出注入时保存的数据,然后loadInto()相关数据到War变量是什么意思ehouse.routes里边去了。
  • 第2次,咱们仅仅是给参数postcard赋值,Destination和Type等。

好,现在咱们的Warehouse.routes有数据了,而且参数postcard有destination和type了,所以接着实施中kotlin和java心函数2:

// 中心函数2
private Object _nakotlin协程原理vi缓存的视频怎样保存到本地gation(final C变量之间的联系ontext context, final Postc缓存视频怎样转入本地视频ard postcappearanceard, final int requestCode, final NavigationCallback callback) {
// 咱们知appreciate道参数context是null,所以就取Arouter.init(cont变量和常量的差异ext)的context,也便是appliKotlincation
final Context cur线程池创立的四种rentContext = null == context ? mContext : context;
//kotlin下载 直接依据类型实施逻辑了
switch (postcard.getType()) {
case ACTIVI变量与函数TY: // 这便是咱们的类型
//app是什么意思 创立intent,destination便是MainActivity.class,咱们在中心函数1里边指定过了
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.线程池创立的四种putExtras(postcard.getExtras());
// Flags,咱们没有设置,便是-1
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activ变量ity)) { // 咱们的context不是Activit变量和常量的差异y
// 所以就增加FLAG_ACTIVITY_NEW_TASK这个Flag(不然用application建议Activity,有的版别会溃散),假定navigation()传递了Activity作为context,就不会增加这个flag
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TAapproachSK);
}
// 设置Action,咱们是没有的
String action = postc缓存视频怎样下载到手机相册ard.getAction();
if (app是什么意思!Te变量名的命名规矩xtUtiAPPls.isEmpty(acti变量on)) {
intent.setAction(action)缓存;
}
// 切换到UI线程去建议Activity,Activity缓存视频兼并app下载建议了,完事。
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(requestCode, currentContext, intent, postcard, callback);
}缓存视频兼并
});
break;
case PROVIDER:
return postcakotlin和javard.getProvider();
case BOARDCAST:
case CONTENT_PROVI线程池面试题DER:
case FRAGMENT:
Class fragmentMeta = postcard.getDestination();
try {
Object instance = fragmentMeta.getConstructor().newInstance();
if (instance instanceoKotlinf Fragment) {
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment变量是什么意思) instance).setArguments(postcard.getExtras());
}
return insappearancetance;
} catch (Exception ex) {
logger.error(Cons线程池的七个参数ts缓存视频怎样下载到手机相册.TAG, "Fetch fragment instance er线程池原理ror, " + TextUtils.formatStackTrace(ex.getStackTrace()));
}
case M线程池作业原理ETHOD:
case SERVICkotlin高阶函数E:
default:
return null;
}
return nu线程池回绝战略ll;
}

中心函app是什么意思数2的逻辑很简答,直接用postcard里边的type去application实施对应逻辑,然后实施到了Activity分支,所以就取出destination,也便是MainActivity.class,来建议。

好,咱们来小结一下appointment:

咱们经过path去navigation(),此path=”app/activity_m缓存视频怎样下载到手机相册ain”,此刻会依据这个path结构一个postCard,其间以group=”app”(以”/”切割得到的),然后以g缓存视频兼并roup(也便是”app”)从Werehouse的groupIndex里边获取值,就得到了”Arouter$$Group$$app.class”这个class政策线程池品种
接着,运用反射创立一个实例,并调用loadInto()函数,所以就实施到了:

atlas.put("/app/activity_main", RouteMeta.build(RouteType.ACTIVITY, MainActivity.clAPPass, "/app/activity_main", "app", null, -1, -2147483648));

尔后,咱们的Werehouse的线程池品种routes里边就有了:

{"/app/activity_main", RouteMeta.build(RouteType.ACTIVITY, MainActiv缓存ity.class, "/app/activity_main", "app"},

接着,依据postCard的类型去进行appearswitch-缓存视频在手机哪里找case,当ckotlin怎样读ase到RouteType.ACTIVITY时,就进行A线程池创立的四种ctivity的建议,此刻咱们有了对应Activitykotlin教程的class,假定navigation(c缓存视频怎样转入相册ontext)传递了context,则就用这个context来建议Activity,不然就用Arouter.init(context)这个context来建议,假定这个context不是activiapproachty,则会增加Intent.FLAG_ACTIVITY_NEW_TASK这个flag来建议Activity。

总结

咱们一路追寻了Arouter的源码流程:appreciate

  • 1 在编译时经过Apt技能来 给代码中含有@Route(path)注解的类 生成中间代码
  • 2 Arouter.init(context)初始化时,进行注入操作,key便是pa线程池参数设置准则th
  • 3 Arouter.getIntstappstoreance().build(path).navigation()时分用path来进行获取操作,究竟获取到要建议的Activity的class政策。

总归,这跟咱们一初步用的common公共依托是相同的,Arouter自身也是被app和login两个mo变量duleapp是什么意思依托的,所以Aro线程池回绝战略uter自身就线程池参数设置准则kotlin协程原理第三方公缓存数据能够铲除吗共依托。

所以,一个大思维便是: 顶层两个互不相通的模块想要通讯,能够仰仗公共依托的底层模块来进行,这儿的模块是广义的泛指,比方两个应用程序彼此通讯能够仰仗系统程序,两个actkotlin协程原理ivity彼此通讯能够仰仗application,乃变量英文至两个类彼此通讯能够仰仗父类。两个小技能便是Apt和类加载,当然也能够不必这两个技能,技能是手段,思维是政策,只要能完结政策,什么都无所谓。

发表评论

提供最优质的资源集合

立即查看 了解详情