ARouter 源碼摸索+實(shí)踐

搭建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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辖试,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子劈狐,更是在濱河造成了極大的恐慌罐孝,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肥缔,死亡現(xiàn)場(chǎng)離奇詭異莲兢,居然都是意外死亡续膳,警方通過查閱死者的電腦和手機(jī)改艇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坟岔,“玉大人谒兄,你說我怎么就攤上這事∩绺叮” “怎么了承疲?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵邻耕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我燕鸽,道長(zhǎng)赊豌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任绵咱,我火速辦了婚禮碘饼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悲伶。我一直安慰自己艾恼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布麸锉。 她就那樣靜靜地躺著钠绍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪花沉。 梳的紋絲不亂的頭發(fā)上柳爽,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音碱屁,去河邊找鬼磷脯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娩脾,可吹牛的內(nèi)容都是我干的赵誓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼柿赊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼俩功!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碰声,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤诡蜓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胰挑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔓罚,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年洽腺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脚粟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蘸朋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扣唱,到底是詐尸還是另有隱情藕坯,我是刑警寧澤团南,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站炼彪,受9級(jí)特大地震影響吐根,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辐马,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一拷橘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喜爷,春花似錦冗疮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至湃密,卻和暖如春诅挑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泛源。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工拔妥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人达箍。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓毒嫡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親幻梯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兜畸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • ARouter探究(一) 前言 ARouter 是 Alibaba 開源的一款 Android 頁(yè)面路由框架,特別...
    Jason騎蝸诺馍遥看世界閱讀 1,336評(píng)論 1 3
  • 本文已獨(dú)家授權(quán) 郭霖 ( guolin_blog) 公眾號(hào)發(fā)布咬摇! 在《探索Android路由框架-ARouter(...
    騎小豬看流星閱讀 19,133評(píng)論 6 93
  • ARouter源碼解讀 以前看優(yōu)秀的開源項(xiàng)目,看到了頁(yè)面路由框架ARouter煞躬,心想頁(yè)面路由是個(gè)啥東東肛鹏,于是乎網(wǎng)上...
    陸元偉閱讀 529評(píng)論 0 1
  • 組件化被越來越多的Android項(xiàng)目采用,而作為組件化的基礎(chǔ)——路由也是重中之重恩沛。本篇文章將詳細(xì)的分析阿里巴巴開源...
    胡奚冰閱讀 14,802評(píng)論 8 32
  • 音樂雖然屬于高雅的藝術(shù)在扰,但也同樣適合我們這些外行欣賞。最近一段時(shí)間雷客,常常在閑暇時(shí)聽一聽音樂芒珠。民族音樂我一直...
    湖畔漁夫閱讀 280評(píng)論 0 4