搭建ARouter環(huán)境
源碼地址 ARouter
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
dependencies {
api 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
...
}
build.gradle 添加引用依賴
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
ARouter.openDebug();
ARouter.openLog();
}
ARouter.init(this);
}
}
MyApplication 添加初始化
public class MainActivity extends AppCompatActivity {
...
public void click1(View view) {
ARouter.getInstance().build("/app/main2").navigation();
}
}
import com.alibaba.android.arouter.facade.annotation.Route;
@Route(path = "/app/main2")
public class Main2Activity extends AppCompatActivity {
...
}
創(chuàng)建MainActivity侥猬,設(shè)置一個(gè)點(diǎn)擊事件通過路由方法跳轉(zhuǎn)Main2Activity
同模塊下跳轉(zhuǎn)
以上是一個(gè)簡(jiǎn)單的實(shí)踐
源碼探索 ARouter.init(this);
首先在剛才 Application 中初始化的時(shí)候我們調(diào)用了 ARouter.init(this);
public final class ARouter {
...
public static void init(Application application) {
...
hasInit = _ARouter.init(application);
...
}
}
先進(jìn)入 ARouter.class
final class _ARouter {
...
private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();
...
protected static synchronized boolean init(Application application) {
mContext = application;
LogisticsCenter.init(mContext, executor);
...
return true;
}
再進(jìn)入下一步 _ARouter.class
- 1 判斷是否是debug模式或者首次啟動(dòng)
- 2 從apk文件中讀取 ARouter 生成的文件
- 3 將讀取到的className map 通過 SharedPreferences 保存下來
- 4 之后App再啟動(dòng)的時(shí)候就不用去讀文件雕沉,直接存緩存的 SP 中讀取
- 5 遍歷map恭理,將讀取到的數(shù)據(jù)保存到 Warehouse.class 的靜態(tài)常量 Map 中
Android studio 生成的 ARouter 文件
public class ARouter$$Group$$app implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/app/main2", RouteMeta.build(RouteType.ACTIVITY, Main2Activity.class, "/app/main2", "app", null, -1, -2147483648));
}
}
public class ARouter$$Root$$app implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("app", ARouter$$Group$$app.class);
}
}
public class ARouter$$Providers$$app implements IProviderGroup {
@Override
public void loadInto(Map<String, RouteMeta> providers) {
}
}
public interface IRouteGroup {
public interface IRouteRoot {
public interface IInterceptorGroup {
void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptor);
}
以上是 ARouter 生成的文件,繼承的接口都是用于讀取數(shù)據(jù)保存到 Warehouse.class 用的
源碼探索 ARouter.getInstance().build(String path)
- 1 PathReplaceService extends IProvider丰涉,當(dāng)你的一個(gè)模塊有一個(gè)類繼承了PathReplaceService,并重寫了它的兩個(gè)方法方法斯碌,在這里就可以進(jìn)行path的預(yù)處理一死,動(dòng)態(tài)替換我們最終的目的地。
- 2 進(jìn)入下一步4
- 3 這個(gè)方法校驗(yàn)?zāi)愕膒ath是否寫的正確傻唾,格式必須是 /xx/xx 投慈,這個(gè)reture 的是 “app”
- 3A 這里將繼承了 IProvider 的類進(jìn)行init承耿,和fragment一起都是綠色通道默認(rèn)不攔截
- 4 最終生成一個(gè) Postcard 對(duì)象
public final class Postcard extends RouteMeta {
// Base
private Uri uri;
private Object tag; // A tag prepare for some thing wrong.
private Bundle mBundle; // Data to transform
private int flags = -1; // Flags of route
private int timeout = 300; // Navigation timeout, TimeUnit.Second
private IProvider provider; // It will be set value, if this postcard was provider.
private boolean greenChannel;
private SerializationService serializationService;
// Animation
private Bundle optionsCompat; // The transition animation of activity
private int enterAnim = -1;
private int exitAnim = -1;
public class RouteMeta {
private RouteType type; // Type of route
private Element rawType; // Raw type of route
private Class<?> destination; // Destination
private String path; // Path of route
private String group; // Group of route
private int priority = -1; // The smaller the number, the higher the priority
private int extra; // Extra data
private Map<String, Integer> paramsType; // Param type
private String name;
private Map<String, Autowired> injectConfig; // Cache inject config.
Postcard 繼承 RouteMeta,他們保存了 Intent 的參數(shù)
源碼探索 ARouter.getInstance().build("/app/main2").navigation();
- 1 Postcard 寫入到 LogisticsCenter 保存起來
- 2 Warehouse 中緩存的map數(shù)據(jù)伪煤,通過postcard.getPath()當(dāng)key加袋,查找出已經(jīng)緩存的數(shù)據(jù)
- 3 將對(duì)應(yīng)緩存的數(shù)據(jù),賦值到 postcard
- 4 這邊是綠色通道抱既,不受攔截的意思职烧,可以使用方法 ARouter.getInstance().build(“xx").greenChannel() 來調(diào)用,這部分還有攔截器的操作防泵,那個(gè)callback 就是攔截器的監(jiān)聽事件蚀之,注冊(cè)了就會(huì)開始走這部分邏輯
- 5 下一步
- 6 開始區(qū)分類型,這是打開 Activity 頁(yè)面的操作捷泞,當(dāng) context 不是 instanceof Activity時(shí)足删,表示當(dāng)前不是從APP內(nèi)部打開的,需要加上 flag Intent.FLAG_ACTIVITY_NEW_TASK锁右,打開一個(gè)新的頁(yè)面
- 7 判斷是否主線程壹堰,最終由主線程來調(diào)用startActivity方法
- 8 requestCode >=0 表示需要下一個(gè)頁(yè)面的反饋然后調(diào)用 startActivityForResult,并傳遞Bundle數(shù)據(jù)
- 9 頁(yè)面跳轉(zhuǎn)的動(dòng)畫
- 10 類型的區(qū)分骡湖,比較熟悉的Fragment通過反射拿到實(shí)例贱纠,并判斷Fragment的版本類型,provider 類型的直接返回接口實(shí)例响蕴,可以強(qiáng)轉(zhuǎn)成本地的對(duì)象谆焊,這樣就能調(diào)用對(duì)應(yīng)的本地方法了
a.gif
TestService mNavigation = (TestService) ARouter.getInstance().build("/test/service").navigation();
mTextView.setText(mNavigation.getNum());
@Route(path = "/test/service")
public class TestService implements IProvider {
@Override
public void init(Context context) {
Log.d("TestService", "init");
}
public String getNum() {
return String.valueOf(Constant.NUM);
}
}
這是一個(gè) IProvider 的操作的實(shí)例效果,獲取其他模塊的簡(jiǎn)單數(shù)據(jù)操作
這部分代碼鏈接
這樣下來基本的源碼流程已經(jīng)走完浦夷,剩下的一些操作傳數(shù)據(jù)攔截器什么都源碼中也都能很直觀的看出來
探索Android路由框架-ARouter之深挖源碼(二)
談?wù)凙pp的統(tǒng)一跳轉(zhuǎn)和ARouter