{"id":33,"date":"2021-09-17T10:15:02","date_gmt":"2021-09-17T02:15:02","guid":{"rendered":"http:\/\/blog.pbin.xin\/?p=33"},"modified":"2021-09-17T10:15:02","modified_gmt":"2021-09-17T02:15:02","slug":"%e3%80%90android%e3%80%91arouter","status":"publish","type":"post","link":"http:\/\/blog.percy.homes\/index.php\/2021\/09\/17\/%e3%80%90android%e3%80%91arouter\/","title":{"rendered":"\u3010Android\u3011ARouter"},"content":{"rendered":"<h1>\u3010\u7b14\u8bb0\u3011\u3010Android\u3011ARouter<\/h1>\n<h2>\u4ecb\u7ecd<\/h2>\n<p>\u4e00\u4e2a\u7528\u4e8e\u5e2e\u52a9 Android App \u8fdb\u884c\u7ec4\u4ef6\u5316\u6539\u9020\u7684\u6846\u67b6 \u2014\u2014 \u652f\u6301\u6a21\u5757\u95f4\u7684\u8def\u7531\u3001\u901a\u4fe1\u3001\u89e3\u8026<\/p>\n<ul>\n<li><strong>\u652f\u6301\u76f4\u63a5\u89e3\u6790\u6807\u51c6 URL \u8fdb\u884c\u8df3\u8f6c\uff0c\u5e76\u81ea\u52a8\u6ce8\u5165\u53c2\u6570\u5230\u76ee\u6807\u9875\u9762\u4e2d<\/strong><\/li>\n<li>\u652f\u6301\u591a\u6a21\u5757\u5de5\u7a0b\u4f7f\u7528<\/li>\n<li><strong>\u652f\u6301\u6dfb\u52a0\u591a\u4e2a\u62e6\u622a\u5668\uff0c\u81ea\u5b9a\u4e49\u62e6\u622a\u987a\u5e8f<\/strong><\/li>\n<li>\u652f\u6301\u4f9d\u8d56\u6ce8\u5165\uff0c\u53ef\u5355\u72ec\u4f5c\u4e3a\u4f9d\u8d56\u6ce8\u5165\u6846\u67b6\u4f7f\u7528<\/li>\n<li>\u652f\u6301 InstantRun<\/li>\n<li>\u652f\u6301 MultiDex (Google \u65b9\u6848)<\/li>\n<li>\u6620\u5c04\u5173\u7cfb\u6309\u7ec4\u5206\u7c7b\u3001\u591a\u7ea7\u7ba1\u7406\uff0c\u6309\u9700\u521d\u59cb\u5316<\/li>\n<li><strong>\u652f\u6301\u7528\u6237\u6307\u5b9a\u5168\u5c40\u964d\u7ea7\u4e0e\u5c40\u90e8\u964d\u7ea7\u7b56\u7565<\/strong><\/li>\n<li><strong>\u9875\u9762\u3001\u62e6\u622a\u5668\u3001\u670d\u52a1\u7b49\u7ec4\u4ef6\u5747\u81ea\u52a8\u6ce8\u518c\u5230\u6846\u67b6<\/strong><\/li>\n<li>\u652f\u6301\u591a\u79cd\u65b9\u5f0f\u914d\u7f6e\u8f6c\u573a\u52a8\u753b<\/li>\n<li><strong>\u652f\u6301\u83b7\u53d6 Fragment<\/strong><\/li>\n<li>\u5b8c\u5168\u652f\u6301 Kotlin \u4ee5\u53ca\u6df7\u7f16<\/li>\n<li>\u652f\u6301\u7b2c\u4e09\u65b9 App \u52a0\u56fa (\u4f7f\u7528 arouter-register \u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c)<\/li>\n<li>\u652f\u6301\u751f\u6210\u8def\u7531\u6587\u6863<\/li>\n<li>\u63d0\u4f9b IDE \u63d2\u4ef6\u4fbf\u6377\u7684\u5173\u8054\u8def\u5f84\u548c\u76ee\u6807\u7c7b<\/li>\n<\/ul>\n<h2>\u5178\u578b\u5e94\u7528<\/h2>\n<ul>\n<li><strong>\u4ece\u5916\u90e8 URL \u6620\u5c04\u5230\u5185\u90e8\u9875\u9762\uff0c\u4ee5\u53ca\u53c2\u6570\u4f20\u9012\u4e0e\u89e3\u6790<\/strong><\/li>\n<li>\u8de8\u6a21\u5757\u9875\u9762\u8df3\u8f6c\uff0c\u6a21\u5757\u95f4\u89e3\u8026<\/li>\n<li><strong>\u62e6\u622a\u8df3\u8f6c\u8fc7\u7a0b\uff0c\u5904\u7406\u767b\u9646\u3001\u57cb\u70b9\u7b49\u903b\u8f91<\/strong><\/li>\n<li>\u8de8\u6a21\u5757 API \u8c03\u7528\uff0c\u901a\u8fc7\u63a7\u5236\u53cd\u8f6c\u6765\u505a\u7ec4\u4ef6\u89e3\u8026<\/li>\n<\/ul>\n<h2>\u4f18\u52bf<\/h2>\n<ul>\n<li><strong>\u76f4\u63a5\u89e3\u6790 URL \u8def\u7531\uff0c\u89e3\u6790\u53c2\u6570\u5e76\u8d4b\u503c\u5230\u5bf9\u5e94\u76ee\u6807\u5b57\u6bb5\u7684\u9875\u9762\u4e2d\u3002<\/strong><\/li>\n<li>\u652f\u6301\u591a\u6a21\u5757\u9879\u76ee\uff0c\u56e0\u4e3a\u73b0\u5728\u5f88\u5c11\u6709 APP \u662f\u5355\u6a21\u5757\u7684\u9879\u76ee\uff0c\u4e00\u822c\u90fd\u662f\u591a\u6a21\u5757\u5355\u5de5\u7a0b\u7684\uff0c\u7531\u4e0d\u540c\u7684\u56e2\u961f\u8d1f\u8d23\u4e0d\u540c\u7684\u6a21\u5757\u5f00\u53d1\uff0c\u8fd9\u65f6\u5019\u652f\u6301\u591a\u6a21\u5757\u9879\u76ee\u5f00\u53d1\u5c31\u663e\u5f97\u5c24\u4e3a\u91cd\u8981<\/li>\n<li>\u652f\u6301 InstantRun\uff0c\u76ee\u524d\u5f88\u591a\u8def\u7531\u6846\u67b6\u5e76\u4e0d\u652f\u6301 InstantRun\uff0c\u800c InstantRun \u662f Google \u5728 AndroidStudio2.0 \u963f\u5c14\u6cd5\u7248\u672c\u4e2d\u63d0\u4f9b\u7684\u65b0\u529f\u80fd\uff0c\u5176\u7c7b\u4f3c\u4e8e\u4ee3\u7801\u7684\u65e5\u66f4\u65b0\uff0c\u5176\u53ea\u4e0d\u8fc7\u9762\u5411\u7684\u662f\u5f00\u53d1\u8fc7\u7a0b\uff0c\u8fd9\u6837\u505a\u53ef\u4ee5\u5728\u5f00\u53d1\u7684\u8fc7\u7a0b\u4e2d\u51cf\u5c11\u5f00\u53d1\u548c\u7f16\u8bd1\u7684\u6b21\u6570\uff0c\u53ef\u4ee5\u7b80\u5355\u5730\u5c06\u4ee3\u7801\u4fee\u6539\u5373\u65f6\u5730\u540c\u6b65\u5230 APK \u4e2d\uff0c\u4ece\u800c\u53ef\u4ee5\u5927\u89c4\u6a21\u964d\u4f4e\u5f00\u53d1\u590d\u6742\u5ea6\u3002<\/li>\n<li><strong>\u5141\u8bb8\u81ea\u5b9a\u4e49\u62e6\u622a\u5668\uff0cARouter \u662f\u652f\u6301\u62e6\u622a\u5668\u7684\uff0c\u800c\u62e6\u622a\u5668\u5176\u5b9e\u5c31\u662f AOP \u7684\u5b9e\u73b0\uff0c\u53ef\u4ee5\u81ea\u5b9a\u4e49\u591a\u4e2a\u62e6\u622a\u5668\u89e3\u51b3\u4e00\u4e9b\u9762\u5411\u884c\u4e3a\u7f16\u7a0b\u4e0a\u51fa\u73b0\u7684\u95ee\u9898\u3002<\/strong><\/li>\n<li>ARouter \u53ef\u4ee5\u63d0\u4f9b IoC \u5bb9\u5668\uff0cIoC \u5176\u5b9e\u5c31\u662f\u63a7\u5236\u53cd\u8f6c\uff0c\u8fd9\u4e00\u90e8\u5206\u505a\u8fc7\u670d\u52a1\u7aef\u5f00\u53d1\u7684\u670b\u53cb\u53ef\u80fd\u6bd4\u8f83\u4e86\u89e3\uff0c\u56e0\u4e3a\u670d\u52a1\u7aef\u5f00\u53d1\u7ecf\u5e38\u7528\u5230\u7684 Spring \u6846\u67b6\u80fd\u591f\u63d0\u4f9b\u7684\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u80fd\u529b\u5c31\u662f\u63a7\u5236\u53cd\u8f6c\u3002<\/li>\n<li>\u6620\u5c04\u5173\u7cfb\u81ea\u52a8\u6ce8\u518c\uff0c\u5728\u9875\u9762\u4e0d\u662f\u5f88\u591a\u7684\u5c0f\u578b APP \u4e0a\u9762\uff0c\u81ea\u52a8\u6ce8\u518c\u5e76\u4e0d\u4f1a\u4f53\u73b0\u51fa\u592a\u5927\u4f18\u52bf\uff0c\u4f46\u662f\u5bf9\u4e8e\u5927\u578b APP \u800c\u8a00\uff0c\u53ef\u80fd\u9875\u9762\u6570\u91cf\u5df2\u7ecf\u8fbe\u5230\u7684\u51e0\u5341\u4e2a\u6216\u8005\u6570\u767e\u4e2a\uff0c\u5728\u8fd9\u6837\u7684\u60c5\u51b5\u4e0b\uff0c\u81ea\u52a8\u6ce8\u518c\u5c31\u663e\u5f97\u975e\u5e38\u91cd\u8981\u4e86\uff0c\u56e0\u4e3a\u4e0d\u53ef\u80fd\u5c06\u6bcf\u4e00\u4e2a\u9875\u9762\u90fd\u901a\u8fc7\u4ee3\u7801\u7684\u65b9\u5f0f\u8fdb\u884c\u6ce8\u518c\u3002<\/li>\n<li><strong>\u7075\u6d3b\u7684\u964d\u7ea7\u7b56\u7565\uff0cARouter \u53ef\u4ee5\u63d0\u4f9b\u5f88\u591a\u79cd\u964d\u7ea7\u7b56\u7565\u4f9b\u7528\u6237\u81ea\u884c\u9009\u62e9\uff0c\u800c\u539f\u751f\u7684\u8def\u7531\u65b9\u6848\u5b58\u5728\u65e0\u6cd5\u7075\u6d3b\u964d\u7ea7\u7684\u95ee\u9898\uff0cStartActivity () \u4e00\u65e6\u5931\u8d25\u5c06\u4f1a\u629b\u51fa\u8fd0\u8425\u7ea7\u5f02\u5e38\u3002<\/strong><\/li>\n<\/ul>\n<h1>\u4f7f\u7528<\/h1>\n<h2>\u57fa\u672c\u4f7f\u7528\u53ca\u9875\u9762\u6ce8\u518c\u6e90\u7801\u89e3\u6790<\/h2>\n<ul>\n<li>\u5728\u4f7f\u7528\u4e4b\u524d\u9700\u8981\u5148\u914d\u7f6e gradle\uff0c\u76ee\u524d api \u6700\u65b0\u7684\u7248\u672c\u662f 1.3.1\uff0c\u5904\u7406\u5668\u7684\u6700\u65b0\u7248\u672c\u662f 1.1.4<\/li>\n<\/ul>\n<pre><code class=\"java\">dependencies {\n    \/\/ \u66ff\u6362\u6210\u6700\u65b0\u7248\u672c, \u9700\u8981\u6ce8\u610f\u7684\u662fapi\n    \/\/ \u8981\u4e0ecompiler\u5339\u914d\u4f7f\u7528\uff0c\u5747\u4f7f\u7528\u6700\u65b0\u7248\u53ef\u4ee5\u4fdd\u8bc1\u517c\u5bb9\n    implementation 'com.alibaba:arouter-api:1.3.1'\n    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'\n    ...\n}\n<\/code><\/pre>\n<ul>\n<li>\u63a5\u7740\u9700\u8981\u5c3d\u65e9\u7684\u521d\u59cb\u5316 ARouter\uff0c\u53ef\u4ee5\u8003\u8651\u5728 Application \u4e2d\u8fdb\u884c\u521d\u59cb\u5316\uff1a<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.init(mApplication);\n<\/code><\/pre>\n<ul>\n<li>\u5728\u9700\u8981\u652f\u6301\u8def\u7531\u8df3\u8f6c\u7684\u9875\u9762\u4e0a\u6dfb\u52a0 @Route \u6ce8\u89e3\uff0c\u8def\u5f84 path \u81f3\u5c11\u9700\u8981\u6709\u4e24\u7ea7\uff0c\u6bd4\u5982\u9700\u8981\u8df3\u8f6c\u5230 LoginActivity, \u90a3\u4e48\u9700\u8981\u5728 Activity \u4e0a\u9762\u914d\u7f6e path, \u4f8b\u5982 \/activity\/LoginActivity\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">@Route(path = \"\/activity\/LoginActivity\")\npublic class LoginActivity extends BaseActivity&lt; LoginActivityIMP&gt; implements LoginActivityContract.View\n<\/code><\/pre>\n<ul>\n<li>\u7136\u540e\u76f4\u63a5\u50cf\u4e0b\u9762\u8fd9\u6837\u5c31\u5c31\u53ef\u4ee5\u5b9e\u73b0\u7b80\u5355\u7684\u8df3\u8f6c\u4e86<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/activity\/LoginActivity\").navigation();\n<\/code><\/pre>\n<ul>\n<li>\u5982\u679c\u9700\u8981\u643a\u5e26\u53c2\u6570\u8df3\u8f6c\u7684\u8bdd\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837<\/li>\n<li>ARouter \u63d0\u4f9b\u4e86\u5f88\u591a\u7684 withXX \u65b9\u6cd5\uff0c\u53ef\u4ee5\u643a\u5e26\u57fa\u672c\u7c7b\u578b\uff0cObject,Parcelable \u7b49\u7b49\uff0c\u91cc\u9762\u7684\u539f\u7406\u4e5f\u662f\u901a\u8fc7 Bundle \u8fdb\u884c\u643a\u5e26 mBundle.putXX \u5b9e\u73b0<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/activity\/LoginActivity\").withString(\"key\", \"value\").navigation();\n<\/code><\/pre>\n<ul>\n<li>\u5982\u679c\u9700\u8981\u5b9e\u73b0\u7c7b\u4f3c startActivityForResult, \u53ea\u9700\u8981\u5728 navigation \u4e2d\u4f20\u5165\u4e24\u4e2a\u53c2\u6570\uff0c\u7b2c\u4e00\u4e2a\u5c31\u662f Context\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f requestCode\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/activity\/LoginActivity\").navigation(this,1);\n<\/code><\/pre>\n<h2>\u9875\u9762\u8df3\u8f6c\u6e90\u7801\u5206\u6790<\/h2>\n<ul>\n<li>ARouter.getInstance (), \u662f\u83b7\u5f97 ARouter.init (mApplication) \u521d\u59cb\u5316\u7684\u4e8b\u4f8b<\/li>\n<\/ul>\n<pre><code class=\"java\">public static ARouter getInstance() {\n        if (!hasInit) {\n            throw new InitException(\"ARouter::Init::Invoke init(context) first!\");\n        } else {\n            if (instance == null) {\n                synchronized (ARouter.class) {\n                    if (instance == null) {\n                        instance = new ARouter();\n                    }\n                }\n            }\n            return instance;\n        }\n}\n<\/code><\/pre>\n<ul>\n<li>\u7136\u540e.build () \u6784\u9020\u8def\u7531\u4fe1\u606f\u7684\u5bb9\u5668 Postcard<\/li>\n<\/ul>\n<pre><code class=\"java\">public Postcard build(String path) {\n        return _ARouter.getInstance().build(path);\n}\n<\/code><\/pre>\n<ul>\n<li>\u5f97\u5230 ARouter \u5b9e\u4f8b\u540e\u8c03\u7528 build \u65b9\u6cd5\uff0c\u4f20\u5165\u76ee\u6807\u9875\u9762\u7684 path (&#8220;\/activity\/LoginActivity&#8221;)\uff0c\u6211\u4eec\u6765\u770b\u770b build \u7684\u6e90\u7801\u3002\u5176\u5b9e\u662f\u8c03\u7528_ARouter \u7684 build \u65b9\u6cd5\uff0c\u8fd9\u91cc\u9700\u8981\u63d0\u7684\u4e00\u70b9\u662f ARouter.init \u4e5f\u662f\u8c03\u7528\u7684_ARouter \u7684 init \u65b9\u6cd5<\/li>\n<\/ul>\n<pre><code class=\"java\">public static void init(Application application) {\n        if (!hasInit) {\n            logger = _ARouter.logger;\n            _ARouter.logger.info(Consts.TAG, \"ARouter init start.\");\n            hasInit = _ARouter.init(application);\n\n            if (hasInit) {\n                _ARouter.afterInit();\n            }\n\n            _ARouter.logger.info(Consts.TAG, \"ARouter init over.\");\n        }\n}\n<\/code><\/pre>\n<ul>\n<li>\u7136\u540e\u5728\u770b_ARouter \u7684 build \u65b9\u6cd5<\/li>\n<\/ul>\n<pre><code class=\"java\">protected Postcard build(String path) {\n        if (TextUtils.isEmpty(path)) {\n            throw new HandlerException(Consts.TAG + \"Parameter is invalid!\");\n        } else {\n            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);\n            if (null != pService) {\n                path = pService.forString(path);\n            }\n            return build(path, extractGroup(path));\n        }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">protected Postcard build(String path, String group) {\n        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {\n            throw new HandlerException(Consts.TAG + \"Parameter is invalid!\");\n        } else {\n            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);\n            if (null != pService) {\n                path = pService.forString(path);\n            }\n            return new Postcard(path, group);\n        }\n}\n<\/code><\/pre>\n<ul>\n<li>\u5728 new Postcard (path, group) \u4e2d\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u5c31\u662f\u8def\u5f84\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u7ec4\u522b\u4fe1\u606f\u3002 \u6bd4\u5982 &#8220;\/activity\/LoginActivity&#8221; \u6765\u8bf4 activity \u5c31\u662f group\u3002ARouter \u6846\u67b6\u662f\u5206\u7ec4\u7ba1\u7406\uff0c\u6309\u9700\u52a0\u8f7d\u3002\u89e3\u91ca\u8d77\u6765\u5c31\u662f\uff0c\u5728\u7f16\u8bd1\u671f\u6846\u67b6\u626b\u63cf\u4e86\u6240\u6709\u7684\u6ce8\u518c\u9875\u9762\uff0f\u670d\u52a1\uff0f\u5b57\u6bb5\uff0f\u62e6\u622a\u5668\u7b49\uff0c\u90a3\u4e48\u5f88\u660e\u663e\u8fd0\u884c\u671f\u4e0d\u53ef\u80fd\u4e00\u80a1\u8111\u5168\u90e8\u52a0\u8f7d\u8fdb\u6765\uff0c \u8fd9\u6837\u5c31\u592a\u4e0d\u548c\u8c10\u4e86\u3002\u6240\u4ee5\u5c31\u5206\u7ec4\u6765\u7ba1\u7406\uff0cARouter \u5728\u521d\u59cb\u5316\u7684\u65f6\u5019\u53ea\u4f1a\u4e00\u6b21\u6027\u5730\u52a0\u8f7d\u6240\u6709\u7684 root \u7ed3\u70b9\uff0c\u800c\u4e0d\u4f1a\u52a0\u8f7d\u4efb\u4f55\u4e00\u4e2a Group \u7ed3\u70b9\uff0c\u8fd9\u6837\u5c31\u4f1a\u6781\u5927\u5730\u964d\u4f4e\u521d\u59cb\u5316\u65f6\u52a0\u8f7d\u7ed3\u70b9\u7684\u6570\u91cf\u3002 \u6bd4\u5982\u67d0\u4e9b Activity \u5206\u6210\u4e00\u7ec4\uff0c\u7ec4\u540d\u5c31\u53eb activity\uff0c\u7136\u540e\u5728\u7b2c\u4e00\u6b21\u9700\u8981\u52a0\u8f7d\u7ec4\u5185\u7684\u67d0\u4e2a\u9875\u9762\u65f6\u518d\u5c06 activity \u8fd9\u4e2a\u7ec4\u52a0\u8f7d\u8fdb\u6765\u3002<\/li>\n<li>\u6700\u540e\u4e00\u4e2a\u65b9\u6cd5.navigation (), \u65b9\u6cd5\u6700\u540e\u4f1a\u6765\u5230_ARouter \u7684 navigation \u65b9\u6cd5<\/li>\n<\/ul>\n<pre><code class=\"java\">protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {\n        try {\n            LogisticsCenter.completion(postcard);\n        } catch (NoRouteFoundException ex) {\n            logger.warning(Consts.TAG, ex.getMessage());\n            \u2026\u2026\n            if (null != callback) {\/\/\u5982\u679c\u6709\u56de\u8c03\u5c31\u8fdb\u884c\u56de\u8c03\n                callback.onLost(postcard);\n            } else {    \/\/ No callback for this invoke, then we use the global degrade service.\n                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);\n                if (null != degradeService) {\n                    degradeService.onLost(context, postcard);\n                }\n            }\n\n            return null;\n        }\n\n        if (null != callback) {\n            callback.onFound(postcard);\n        }\n        if (!postcard.isGreenChannel()) { \/\/\u5982\u679c\u9700\u8981\u62e6\u622a\n        \u2026\u2026\n        } else {\/\/\u4e0d\u9700\u8981\u62e6\u622a\n            return _navigation(context, postcard, requestCode, callback);\n        }\n\n        return null;\n}\n<\/code><\/pre>\n<ul>\n<li>\u9996\u5148\u8c03\u7528 LogisticsCenter.completion \u5b8c\u6210 postcard \u7684\u8865\u5145<\/li>\n<\/ul>\n<pre><code class=\"java\">\/**\n     * Completion the postcard by route metas\n     *\n     * @param postcard Incomplete postcard, should completion by this method.\n     *\/\n    public synchronized static void completion(Postcard postcard) {\n        if (null == postcard) {\n            throw new NoRouteFoundException(TAG + \"No postcard!\");\n        }\n\n        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());\n        if (null == routeMeta) {    \/\/ Maybe its does't exist, or didn't load.\n            Class&lt; ? extends IRouteGroup&gt; groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  \/\/ Load route meta.\n            if (null == groupMeta) {\n                throw new NoRouteFoundException(TAG + \"There is no route match the path [\" + postcard.getPath() + \"], in group [\" + postcard.getGroup() + \"]\");\n            } else {\n                \/\/ Load route and cache it into memory, then delete from metas.\n                try {\n                    if (ARouter.debuggable()) {\n                        logger.debug(TAG, String.format(Locale.getDefault(), \"The group [%s] starts loading, trigger by [%s]\", postcard.getGroup(), postcard.getPath()));\n                    }\n\n                    IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();\n                    iGroupInstance.loadInto(Warehouse.routes);\n                    Warehouse.groupsIndex.remove(postcard.getGroup());\n\n                    if (ARouter.debuggable()) {\n                        logger.debug(TAG, String.format(Locale.getDefault(), \"The group [%s] has already been loaded, trigger by [%s]\", postcard.getGroup(), postcard.getPath()));\n                    }\n                } catch (Exception e) {\n                    throw new HandlerException(TAG + \"Fatal exception when loading group meta. [\" + e.getMessage() + \"]\");\n                }\n\n                completion(postcard);   \/\/ Reload\n            }\n        } else {\n            postcard.setDestination(routeMeta.getDestination());\n            postcard.setType(routeMeta.getType());\n            postcard.setPriority(routeMeta.getPriority());\n            postcard.setExtra(routeMeta.getExtra());\n\n            Uri rawUri = postcard.getUri();\n            if (null != rawUri) {   \/\/ Try to set params into bundle.\n                Map&lt; String, String&gt; resultMap = TextUtils.splitQueryParameters(rawUri);\n                Map&lt; String, Integer&gt; paramsType = routeMeta.getParamsType();\n\n                if (MapUtils.isNotEmpty(paramsType)) {\n                    \/\/ Set value by its type, just for params which annotation by @Param\n                    for (Map.Entry&lt; String, Integer&gt; params : paramsType.entrySet()) {\n                        setValue(postcard,\n                                params.getValue(),\n                                params.getKey(),\n                                resultMap.get(params.getKey()));\n                    }\n\n                    \/\/ Save params name which need auto inject.\n                    postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));\n                }\n\n                \/\/ Save raw uri\n                postcard.withString(ARouter.RAW_URI, rawUri.toString());\n            }\n\n            switch (routeMeta.getType()) {\n                case PROVIDER:  \/\/ if the route is provider, should find its instance\n                    \/\/ Its provider, so it must be implememt IProvider\n                    Class&lt; ? extends IProvider&gt; providerMeta = (Class&lt; ? extends IProvider&gt;) routeMeta.getDestination();\n                    IProvider instance = Warehouse.providers.get(providerMeta);\n                    if (null == instance) { \/\/ There's no instance of this provider\n                        IProvider provider;\n                        try {\n                            provider = providerMeta.getConstructor().newInstance();\n                            provider.init(mContext);\n                            Warehouse.providers.put(providerMeta, provider);\n                            instance = provider;\n                        } catch (Exception e) {\n                            throw new HandlerException(\"Init provider failed! \" + e.getMessage());\n                        }\n                    }\n                    postcard.setProvider(instance);\n                    postcard.greenChannel();    \/\/ Provider should skip all of interceptors\n                    break;\n                case FRAGMENT:\n                    postcard.greenChannel();    \/\/ Fragment needn't interceptors\n                default:\n                    break;\n            }\n        }\n}\n<\/code><\/pre>\n<ul>\n<li>\u56e0\u4e3a\u662f\u6309\u9700\u52a0\u8f7d\uff0c\u6240\u4ee5 RouteMeta routeMeta = Warehouse.routes.get (postcard.getPath ()); \u4e00\u5f00\u59cb\u80af\u5b9a\u662f null \u7684\uff0c\u6240\u4ee5\u9700\u8981\u5230 Warehouse.groupsIndex \u4e2d\u627e\u5230\u7ec4\u522b\u7684\u4fe1\u606f\uff0c\u8fd9\u91cc\u7684 postcard.getGroup () \u5c31\u662f test.<\/li>\n<\/ul>\n<pre><code class=\"java\">Class&lt; ? extends IRouteGroup&gt; groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  \/\/ Load route meta.\n<\/code><\/pre>\n<ul>\n<li>\u7136\u540e\u901a\u8fc7\u53cd\u5c04\u52a0\u8f7d\u8fd9\u4e00\u7ec4\u7c7b\u522b\u7684\u6620\u5c04\u5173\u7cfb\u3002\u7136\u540e\u4ece\u4ed3\u5e93\u4e2d\u5220\u9664\u8fd9\u4e2a\u7ec4\u522b\u4fe1\u606f\u8282\u70b9\uff0c\u9632\u6b62\u91cd\u590d\u52a0\u8f7d\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();\niGroupInstance.loadInto(Warehouse.routes);\nWarehouse.groupsIndex.remove(postcard.getGroup());\n<\/code><\/pre>\n<ul>\n<li>\u7136\u540e\u770b\u770b apt \u751f\u6210\u7684\u6587\u4ef6 ARouter$$Group$$activity \u7684\u5185\u5bb9\uff0c\u5305\u542b\u6709\u76ee\u6807\u9875\u9762\uff0c\u7c7b\u578b\uff0c\u8def\u5f84\uff0c\u7ec4\u522b\uff0c\u53c2\u6570\uff0c\u4f18\u5148\u7ea7\u7b49\u4fe1\u606f\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">\/**\n * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. *\/\npublic class ARouter$Group$activity implements IRouteGroup {\n  @Override\n  public void loadInto(Map&lt; String, RouteMeta&gt; atlas) {\n    atlas.put(\"\/activity\/ClassifyActivity\", RouteMeta.build(RouteType.ACTIVITY, ClassifyActivity.class, \"\/activity\/classifyactivity\", \"activity\", null, -1, -2147483648));\n    atlas.put(\"\/activity\/CreateNoteActivity\", RouteMeta.build(RouteType.ACTIVITY, CreateNoteActivity.class, \"\/activity\/createnoteactivity\", \"activity\", new java.util.HashMap&lt; String, Integer&gt;(){{put(\"keyName\", 8); put(\"mNote\", 10); }}, -1, -2147483648));\n    atlas.put(\"\/activity\/LoginActivity\", RouteMeta.build(RouteType.ACTIVITY, LoginActivity.class, \"\/activity\/loginactivity\", \"activity\", null, -1, -2147483648));\n    atlas.put(\"\/activity\/SearchNoteActivity\", RouteMeta.build(RouteType.ACTIVITY, SearchNoteActivity.class, \"\/activity\/searchnoteactivity\", \"activity\", new java.util.HashMap&lt; String, Integer&gt;(){{put(\"keyName\", 8); }}, -1, -2147483648));\n    atlas.put(\"\/activity\/TODOActivity\", RouteMeta.build(RouteType.ACTIVITY, TODOActivity.class, \"\/activity\/todoactivity\", \"activity\", new java.util.HashMap&lt; String, Integer&gt;(){{put(\"keyName\", 8); }}, -1, -2147483648));\n  }\n}\n<\/code><\/pre>\n<ul>\n<li>\u63a5\u4e0b\u6765\u4f1a\u9012\u5f52\u8c03\u7528 completion (postcard)\uff0c\u73b0\u5728 routeMeta \u5c31\u4e0d\u4e3a\u7a7a\u4e86\uff0c\u4f1a\u8d70\u5230 else \u4e2d\uff0c\u9996\u5148\u7ed9 postcard \u8865\u5145\u4fe1\u606f\uff0c\u6709\u4e86\u8fd9\u4e9b\u4fe1\u606f postcard \u5c31\u53ef\u4ee5\u6109\u5feb\u7684\u5de5\u4f5c\u4e86\u3002\u6211\u4eec\u8fd9\u4e2a\u6817\u5b50\u4e2d type \u5f88\u660e\u663e\u662f activity\uff0c\u6240\u4ee5\u5c31\u8d70\u5230 default \u4e2d break \u51fa\u6765\u4e86\u3002<\/li>\n<li>\u7136\u540e\u6700\u540e\u5230\u4e86\u771f\u6b63\u7684\u8df3\u8f6c\uff0c_navigation () \u8df3\u8f6c\uff0c\u5c31\u662f\u5e38\u89c1\u7684 intent \u548c startActivity\u3001startActivityForResult<\/li>\n<\/ul>\n<pre><code class=\"java\">private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {\n        final Context currentContext = null == context ? mContext : context;\n\n        switch (postcard.getType()) {\n            case ACTIVITY:\n                \/\/ Build intent\n                final Intent intent = new Intent(currentContext, postcard.getDestination());\n                intent.putExtras(postcard.getExtras());\n\n                \/\/ Set flags.\n                int flags = postcard.getFlags();\n                if (-1 != flags) {\n                    intent.setFlags(flags);\n                } else if (!(currentContext instanceof Activity)) {    \/\/ Non activity, need less one flag.\n                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n                }\n\n                \/\/ Navigation in main looper.\n                new Handler(Looper.getMainLooper()).post(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (requestCode &gt; 0) {  \/\/ Need start for result\n                            ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());\n                        } else {\n                            ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());\n                        }\n\n                        if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) &amp;&amp; currentContext instanceof Activity) {    \/\/ Old version.\n                            ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());\n                        }\n\n                        if (null != callback) { \/\/ Navigation over.\n                            callback.onArrival(postcard);\n                        }\n                    }\n                });\n\n                break;\n            case PROVIDER:\n                return postcard.getProvider();\n            case BOARDCAST:\n            case CONTENT_PROVIDER:\n            case FRAGMENT:\n                Class fragmentMeta = postcard.getDestination();\n                try {\n                    Object instance = fragmentMeta.getConstructor().newInstance();\n                    if (instance instanceof Fragment) {\n                        ((Fragment) instance).setArguments(postcard.getExtras());\n                    } else if (instance instanceof android.support.v4.app.Fragment) {\n                        ((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());\n                    }\n\n                    return instance;\n                } catch (Exception ex) {\n                    logger.error(Consts.TAG, \"Fetch fragment instance error, \" + TextUtils.formatStackTrace(ex.getStackTrace()));\n                }\n            case METHOD:\n            case SERVICE:\n            default:\n                return null;\n        }\n\n        return null;\n<\/code><\/pre>\n<h2>Uri \u8df3\u8f6c\u89e3\u6790 (\u5b98\u65b9 demo)<\/h2>\n<ul>\n<li>\u5b98\u65b9demo\u7684html.body<\/li>\n<\/ul>\n<pre><code class=\"html\">&lt; body&gt;\n\n&lt; h2&gt;\u8df3\u8f6c\u6d4b\u8bd5&lt; \/h2&gt;\n\n&lt; h2&gt;\u81ea\u5b9a\u4e49Scheme[\u901a\u5e38\u6765\u8bf4\u90fd\u662f\u8fd9\u6837\u7684]&lt; \/h2&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity1\"&gt;arouter:\/\/m.aliyun.com\/test\/activity1&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity1?url=https%3a%2f%2fm.abc.com%3fa%3db%26c%3dd\"&gt;\u6d4b\u8bd5URL Encode\u60c5\u51b5&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity1?name=alex&amp;age=18&amp;boy=true&amp;high=180&amp;obj=%7b%22name%22%3a%22jack%22%2c%22id%22%3a666%7d\"&gt;arouter:\/\/m.aliyun.com\/test\/activity1?name=alex&amp;age=18&amp;boy=true&amp;high=180&amp;obj={\"name\":\"jack\",\"id\":\"666\"}&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity2\"&gt;arouter:\/\/m.aliyun.com\/test\/activity2&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity2?key1=value1\"&gt;arouter:\/\/m.aliyun.com\/test\/activity2?key1=value1&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"arouter:\/\/m.aliyun.com\/test\/activity3?name=alex&amp;age=18&amp;boy=true&amp;high=180\"&gt;arouter:\/\/m.aliyun.com\/test\/activity3?name=alex&amp;age=18&amp;boy=true&amp;high=180&lt; \/a&gt;&lt; \/p&gt;\n\n&lt; h2&gt;App Links[\u9632\u6b62\u88abApp\u5c4f\u853d]&lt; \/h2&gt;\n&lt; p&gt;&lt; a href=\"http:\/\/m.aliyun.com\/test\/activity1\"&gt;http:\/\/m.aliyun.com\/test\/activity1&lt; \/a&gt;&lt; \/p&gt;\n&lt; p&gt;&lt; a href=\"http:\/\/m.aliyun.com\/test\/activity2\"&gt;http:\/\/m.aliyun.com\/test\/activity2&lt; \/a&gt;&lt; \/p&gt;\n\n&lt; \/body&gt;\n<\/code><\/pre>\n<ul>\n<li>ARouter \u5c31\u662f\u901a\u8fc7\u6ce8\u518c\u4e00\u4e2a\u6ca1\u6709 UI \u7684\u754c\u9762\u6765\u7edf\u4e00\u5904\u7406 scheme \u662f arouter \u7684\u8df3\u8f6c\u8bf7\u6c42\uff0c\u7c7b\u4f3c\u9690\u5f0f\u6ce8\u518c<\/li>\n<\/ul>\n<pre><code class=\"xml\">&lt; activity android:name=\".SchemeFilterActivity\"&gt;\n\n\n            &lt; intent-filter&gt;\n                &lt; data\n                        android:host=\"m.aliyun.com\"\n                        android:scheme=\"arouter\"\/&gt;\n\n                &lt; action android:name=\"android.intent.action.VIEW\"\/&gt;\n\n                &lt; category android:name=\"android.intent.category.DEFAULT\"\/&gt;\n                &lt; category android:name=\"android.intent.category.BROWSABLE\"\/&gt;\n            &lt; \/intent-filter&gt;\n\n\n            &lt; intent-filter android:autoVerify=\"true\"&gt;\n                &lt; action android:name=\"android.intent.action.VIEW\"\/&gt;\n\n                &lt; category android:name=\"android.intent.category.DEFAULT\"\/&gt;\n                &lt; category android:name=\"android.intent.category.BROWSABLE\"\/&gt;\n\n                &lt; data\n                        android:host=\"m.aliyun.com\"\n                        android:scheme=\"http\"\/&gt;\n                &lt; data\n                        android:host=\"m.aliyun.com\"\n                        android:scheme=\"https\"\/&gt;\n            &lt; \/intent-filter&gt;\n        &lt; \/activity&gt;\n<\/code><\/pre>\n<ul>\n<li>\u5728\u6e05\u5355\u6587\u4ef6\u4e2d\u6ce8\u518c\u4e86 SchemeFilterActivity \u8fd9\u4e2a activity\uff0cscheme \u5c31\u662f arouter, host \u5c31\u662f m.aliyun.com\uff0c\u5176\u4e2d\u6709\u4e2a category \u662f android.intent.category.BROWSABLE\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728 WebView \u4e2d\u8df3\u8f6c SchemeFilterActivity \u8fd9\u4e2a\u754c\u9762\u4e86\u3002\u6709\u4e2a\u6ce8\u610f\u70b9\uff0c\u80fd\u8df3\u8f6c SchemeFilterActivity \u7684\u5fc5\u8981\u6761\u4ef6\u5c31\u662f\u9700\u8981\u5339\u914d intent-filter \u4e2d\u7684 data, action, category \u7684\u6807\u7b7e\uff0c\u5176\u4e2d category \u5339\u914d\u4efb\u610f\u4e00\u4e2a\u5373\u53ef\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">public class SchemeFilterActivity extends Activity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n\/\/        \u76f4\u63a5\u901a\u8fc7ARouter\u5904\u7406\u5916\u90e8Uri\n        Uri uri = getIntent().getData();\n        ARouter.getInstance().build(uri).navigation(this, new NavCallback() {\n            @Override\n            public void onArrival(Postcard postcard) {\n                finish();\n            }\n        });\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>Uri uri = getIntent ().getData (); \u83b7\u53d6\u5230\u70b9\u51fb\u7684\u90a3\u4e2a\u503c\uff0c\u4f8b\u5982 arouter:\/\/m.aliyun.com\/test\/activity2, \u7136\u540e\u4ea4\u7ed9\u8def\u7531\u6846\u67b6\u8fdb\u884c\u8df3\u8f6c<\/li>\n<\/ul>\n<h2>\u83b7\u53d6\u670d\u52a1\u548c Fragment (\u5b98\u65b9 demo)<\/h2>\n<ul>\n<li>\u83b7\u53d6\u670d\u52a1<\/li>\n<li>\u8fd9\u91cc\u8bf4\u5230\u7684\u670d\u52a1\u4e0d\u662f Android \u56db\u5927\u7ec4\u4ef6\u4e2d\u7684 Service\uff0c\u8fd9\u91cc\u7684\u670d\u52a1\u662f\u670d\u52a1\u7aef\u5f00\u53d1\u7684\u6982\u5ff5\uff0c\u5c31\u662f\u5c06\u4e00\u90e8\u5206\u529f\u80fd\u548c\u7ec4\u4ef6\u5c01\u88c5\u8d77\u6765\u6210\u4e3a\u63a5\u53e3\uff0c\u4ee5\u63a5\u53e3\u7684\u5f62\u5f0f\u5bf9\u5916\u63d0\u4f9b\u80fd\u529b\uff0c\u6240\u4ee5\u5728\u8fd9\u90e8\u5206\u5c31\u53ef\u4ee5\u5c06\u6bcf\u4e2a\u529f\u80fd\u4f5c\u4e3a\u4e00\u4e2a\u670d\u52a1\uff0c\u800c\u670d\u52a1\u7684\u5b9e\u73b0\u5c31\u662f\u5177\u4f53\u7684\u4e1a\u52a1\u529f\u80fd<\/li>\n<li>ARouter \u53d1\u73b0\u670d\u52a1\u4e3b\u8981\u6709\u4e24\u79cd\u65b9\u5f0f\uff0cByName \u548c ByType\u3002\u5148\u770b\u770b\u8fd9\u4e24\u79cd\u65b9\u5f0f\u5206\u522b\u662f\u600e\u4e48\u4f7f\u7528\u3002ByName \u5c31\u662f\u9700\u8981\u4f20\u9012 path \u8def\u5f84\u6765\u8fdb\u884c\u53d1\u73b0\uff0cByType \u5c31\u662f\u901a\u8fc7\u670d\u52a1 class \u6765\u8fdb\u884c\u67e5\u627e\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">case R.id.navByName:\n    ((HelloService) ARouter.getInstance().build(\"\/yourservicegroupname\/hello\").navigation()).sayHello(\"mike\");\n    break;\ncase R.id.navByType:\n    ARouter.getInstance().navigation(HelloService.class).sayHello(\"mike\");\n    break;\n<\/code><\/pre>\n<pre><code class=\"java\">public interface HelloService extends IProvider {\n    void sayHello(String name);\n}\n<\/code><\/pre>\n<pre><code class=\"java\">@Route(path = \"\/yourservicegroupname\/hello\")\npublic class HelloServiceImpl implements HelloService {\n    Context mContext;\n\n    @Override\n    public void sayHello(String name) {\n        Toast.makeText(mContext, \"Hello \" + name, Toast.LENGTH_SHORT).show();\n    }\n\n    \/**\n     * Do your init work in this method, it well be call when processor has been load.\n     *\n     * @param context ctx\n     *\/\n    @Override\n    public void init(Context context) {\n        mContext = context;\n        Log.e(\"testService\", HelloService.class.getName() + \" has init.\");\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\u83b7\u53d6 Fragment<\/li>\n<\/ul>\n<pre><code class=\"java\">Fragment fragment = (Fragment) ARouter.getInstance().build(\"\/test\/fragment\").navigation();\n<\/code><\/pre>\n<ul>\n<li>ByName \u548c Fragment \u7684\u83b7\u53d6\u548c Activity \u7684\u8df3\u8f6c\u5f88\u50cf\u3002\u5148\u770b\u770b ByType \u7684\u83b7\u53d6\u8fc7\u7a0b\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().navigation(HelloService.class);\n<\/code><\/pre>\n<ul>\n<li>\u8df3\u5230\u5230_ARouter \u7684 navigation (Class&lt; ? extends T&gt; service) \u4e2d\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">protected &lt; T&gt; T navigation(Class&lt; ? extends T&gt; service) {\n        try {\n            Postcard postcard = LogisticsCenter.buildProvider(service.getName());\n\n            \/\/ Compatible 1.0.5 compiler sdk.\n            if (null == postcard) { \/\/ No service, or this service in old version.\n                postcard = LogisticsCenter.buildProvider(service.getSimpleName());\n            }\n\n            LogisticsCenter.completion(postcard);\n            return (T) postcard.getProvider();\n        } catch (NoRouteFoundException ex) {\n            logger.warning(Consts.TAG, ex.getMessage());\n            return null;\n        }\n}\n<\/code><\/pre>\n<p>-\u4e0a\u9762\u4ee3\u7801\u4e3b\u8981\u5c31\u662f\u4e24\u6b65\uff0c\u7b2c\u4e00\u6784\u9020 postcard\uff0c\u7b2c\u4e8c LogisticsCenter \u8df3\u8f6c<\/p>\n<ul>\n<li>\u6784\u9020 postcard<\/li>\n<li>\u9996\u5148\u8fd8\u662f\u719f\u6089\u7684\u5148\u6784\u9020 postcard\uff0c\u53ea\u4e0d\u8fc7\u8fd9\u91cc\u65f6\u76f4\u63a5\u5728 navigation \u4e2d\u8fdb\u884c\u6784\u9020\uff0c\u4e4b\u524d activity \u6216\u8005 url \u8df3\u8f6c\u90fd\u662f\u901a\u8fc7 build \u6784\u9020\uff0c\u610f\u601d\u90fd\u5dee\u4e0d\u591a\u3002\u770b\u770b LogisticsCenter.buildProvider<\/li>\n<\/ul>\n<pre><code class=\"java\">public static Postcard buildProvider(String serviceName) {\n        RouteMeta meta = Warehouse.providersIndex.get(serviceName);\n\n        if (null == meta) {\n            return null;\n        } else {\n            return new Postcard(meta.getPath(), meta.getGroup());\n        }\n}\n<\/code><\/pre>\n<ul>\n<li>\u6253\u4e2a\u65ad\u70b9\u53d1\u73b0 meta \u4e2d\u6709\u4e2a destination \u5c5e\u6027\u53ef\u4ee5\u62ff\u5230\u5177\u4f53\u7684\u5b9e\u73b0\u7c7b HelloServiceImpl\u3002<\/li>\n<\/ul>\n<p><img decoding=\"async\" alt=\"\u56fe\u7247\u63cf\u8ff0\" src=\"http:\/\/121.196.149.88\/home\/docs\/ARouter\/img\/1.png\" style=\"zoom:50%;\"><\/p>\n<ul>\n<li>\u4e0a\u9762\u7684 meta \u662f\u76f4\u63a5\u4ece\u4ed3\u5e93 Warehouse \u4e2d\u83b7\u53d6\u670d\u52a1\uff0c\u4ed3\u5e93\u7684 providersIndex \u5c31\u662f\u5728_ARouter.init () \u65b9\u6cd5\u91cc\u7684 LogisticsCenter .init () \u4e2d\u52a0\u8f7d\u8fdb\u6765\u7684<\/li>\n<\/ul>\n<pre><code class=\"java\">public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {\n        mContext = context;\n        executor = tpe;\n\n        try {\n            long startInit = System.currentTimeMillis();\n            \/\/billy.qi modified at 2017-12-06\n            \/\/load by plugin first\n            loadRouterMap();\n            if (registerByPlugin) {\n                logger.info(TAG, \"Load router map by arouter-auto-register plugin.\");\n            } else {\n                Set&lt; String&gt; routerMap;\n\n                \/\/ It will rebuild router map every times when debuggable.\n                if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {\n                    logger.info(TAG, \"Run with debug mode or new install, rebuild router map.\");\n                    \/\/ These class was generated by arouter-compiler.\n                    routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);\n                    if (!routerMap.isEmpty()) {\n                        context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();\n                    }\n\n                    PackageUtils.updateVersion(context);    \/\/ Save new version name when router map update finishes.\n                } else {\n                    logger.info(TAG, \"Load router map from cache.\");\n                    routerMap = new HashSet&lt;&gt;(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet&lt; String&gt;()));\n                }\n\n                logger.info(TAG, \"Find router map finished, map size = \" + routerMap.size() + \", cost \" + (System.currentTimeMillis() - startInit) + \" ms.\");\n                startInit = System.currentTimeMillis();\n\n                for (String className : routerMap) {\n                    if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {\n                        \/\/ This one of root elements, load root.\n                        ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);\n                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {\n                        \/\/ Load interceptorMeta\n                        ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);\n                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {\n                        \/\/ Load providerIndex\n                        ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);\n                        }\n                }\n            }\n\n            logger.info(TAG, \"Load root element finished, cost \" + (System.currentTimeMillis() - startInit) + \" ms.\");\n\n            if (Warehouse.groupsIndex.size() == 0) {\n                logger.error(TAG, \"No mapping files were found, check your configuration please!\");\n            }\n\n            if (ARouter.debuggable()) {\n                logger.debug(TAG, String.format(Locale.getDefault(), \"LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]\", Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));\n            }\n        } catch (Exception e) {\n            throw new HandlerException(TAG + \"ARouter init logistics center exception! [\" + e.getMessage() + \"]\");\n        }\n    }\n<\/code><\/pre>\n<ul>\n<li>\u5728 apt \u751f\u6210\u7684\u6587\u4ef6\u4e2d\u627e\u5230 ARouter$$Providers$$app, \u5176\u4e2d\u5c31\u6709\u6211\u4eec\u4e0a\u9762\u4f7f\u7528\u5230\u7684 HelloService\uff0c\u5bf9\u5e94\u7684\u6ce8\u518c\u7c7b\u5c31\u662f HelloServiceImpl .class<\/li>\n<\/ul>\n<pre><code class=\"java\">public class ARouter$Providers$app implements IProviderGroup {\n  @Override\n  public void loadInto(Map&lt; String, RouteMeta&gt; providers) {\n    providers.put(\"com.alibaba.android.arouter.demo.testservice.HelloService\", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, \"\/yourservicegroupname\/hello\", \"yourservicegroupname\", null, -1, -2147483648));\n    providers.put(\"com.alibaba.android.arouter.facade.service.SerializationService\", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, \"\/yourservicegroupname\/json\", \"yourservicegroupname\", null, -1, -2147483648));\n    providers.put(\"com.alibaba.android.arouter.demo.testservice.SingleService\", RouteMeta.build(RouteType.PROVIDER, SingleService.class, \"\/yourservicegroupname\/single\", \"yourservicegroupname\", null, -1, -2147483648));\n  }\n}\n<\/code><\/pre>\n<h2>@Autowired \u6ce8\u89e3\u4e0e\u4f9d\u8d56\u6ce8\u5165<\/h2>\n<ul>\n<li>\u4f7f\u7528 @Autowired \u6ce8\u89e3\u63a5\u6536\u8df3\u8f6c\u4f20\u9012\u8fc7\u6765\u7684\u503c<\/li>\n<\/ul>\n<pre><code class=\"java\">(CreateNoteActivity)\n    @Autowired\n    String keyName;\/\/\u5206\u7ec4\u7c7b\u522b\u540d\n\n    @Autowired\n    Note mNote;\n<\/code><\/pre>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/activity\/CreateNoteActivity\").withString(\"keyName\",\"Note\").navigation();\n\n    ARouter.getInstance().build(\"\/activity\/CreateNoteActivity\")\n                .withObject(\"mNote\",mDatas.get(position))\n                .navigation(this,Constant.EDITE_NOTE_CODE);\n<\/code><\/pre>\n<ul>\n<li>@Autowired String keyName \u7684\u53d8\u91cf\u540d\u8981\u548c\u4f20\u9012\u6765\u7684 key \u540d\u4e00\u6837\uff0c\u6216\u8005\u662f\u7528 @Autowired (name = &#8220;keyName&#8221;) String suibian \u624d\u80fd\u63a5\u6536\u5230\u503c<\/li>\n<li>\u5728\u4f20\u9012\u5bf9\u8c61\u7684\u65f6\u5019\uff0c\u62a5\u4e86\u8fd9\u4e2a\u9519\u8bef<\/li>\n<\/ul>\n<pre><code class=\"java\">java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String com.alibaba.android.arouter.facade.service.SerializationService.object2Json(java.lang.Object)' on a null object reference\n        at com.alibaba.android.arouter.facade.Postcard.withObject(Postcard.java:244)\n<\/code><\/pre>\n<ul>\n<li>\u5173\u4e8e\u5bf9\u8c61\u7684\u4f20\u9012\u6709\u4e24\u79cd\uff0c\u4e00\u79cd\u662f withParcelable () \u65b9\u6cd5\uff0c\u4e0d\u8fc7\u6b64\u65b9\u6cd5\u9700\u8981\u4f20\u9012\u7684\u5bf9\u8c61\u5b9e\u73b0 Parcelable \u63a5\u53e3\uff0c\u8fbe\u5230\u5e8f\u5217\u5316\u7684\u76ee\u7684\uff1b\u53e6\u5916\u4e00\u79cd\u662f withObject () \u65b9\u6cd5\uff0c\u6b64\u65b9\u6cd5\u7684\u539f\u7406\u662f\u5c06\u5b9e\u4f53\u7c7b\u8f6c\u6362\u6210 json \u5b57\u7b26\u4e32\uff0c\u901a\u8fc7 String \u7684\u65b9\u5f0f\u8fdb\u884c\u4f20\u9012\uff0c\u800c\u4e14\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\u9700\u8981\u5b9e\u73b0 SerializationService<\/li>\n<\/ul>\n<pre><code class=\"java\">@Route(path = \"\/ARouter\/SerializationService\")\npublic class JsonServiceImp implements SerializationService {\n    @Override\n    public &lt; T&gt; T json2Object(String input, Class&lt; T&gt; clazz) {\n        return new Gson().fromJson(input,clazz);\n    }\n\n    @Override\n    public String object2Json(Object instance) {\n        return new Gson().toJson(instance);\n    }\n\n    @Override\n    public &lt; T&gt; T parseObject(String input, Type clazz) {\n        return new Gson().fromJson(input,clazz);\n    }\n\n    @Override\n    public void init(Context context) {\n\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>@Autowired \u8fd8\u53ef\u4ee5\u6ce8\u5165\u5bf9\u8c61<\/li>\n<\/ul>\n<pre><code class=\"java\">(CreateNoteActivity)\n    @Autowired\n    DBManager mDBManager;\n<\/code><\/pre>\n<pre><code class=\"java\">@Route(path = \"\/utils\/DBManager\")\npublic class DBManager implements IProvider {\n\n    public DBManager(){\n    }\n\n    @Override\n    public void init(Context context) {\n\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\u5bf9\u5e94\u7684\u7c7b\u4e00\u5b9a\u8981\u5b9e\u73b0 IProvider \u63a5\u53e3\u5e76\u6709\u7a7a\u6784\u9020\u51fd\u6570<\/li>\n<li>\u6700\u540e\uff0c\u8981 @Autowired \u6ce8\u89e3\u751f\u6548\u8fd8\u8981\u5728\u4f7f\u7528\u6ce8\u89e3\u7684\u5730\u65b9\u52a0\u5165 ARouter.getInstance ().inject (this);<\/li>\n<li>\u6765\u5230 ARouter \u7684\u4ee3\u7406\u7c7b_ARouter \u4e2d\uff0c\u9996\u5148\u901a\u8fc7\u4ee5\u6765\u67e5\u627e\u83b7\u53d6 AutowiredService \u7684\u5177\u4f53\u5b9e\u73b0\u7c7b<\/li>\n<\/ul>\n<pre><code class=\"java\">static void inject(Object thiz) {\n        AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build(\"\/arouter\/service\/autowired\").navigation());\n        if (null != autowiredService) {\n            autowiredService.autowire(thiz);\n        }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">@Route(path = \"\/arouter\/service\/autowired\")\npublic class AutowiredServiceImpl implements AutowiredService {\n    private LruCache&lt; String, ISyringe&gt; classCache;\n    private List&lt; String&gt; blackList;\n\n    @Override\n    public void init(Context context) {\n        classCache = new LruCache&lt;&gt;(66);\n        blackList = new ArrayList&lt;&gt;();\n    }\n\n    @Override\n    public void autowire(Object instance) {\n        String className = instance.getClass().getName();\n        try {\n            if (!blackList.contains(className)) {\n                ISyringe autowiredHelper = classCache.get(className);\n                if (null == autowiredHelper) {  \/\/ No cache.\n                    autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();\n                }\n                autowiredHelper.inject(instance);\n                classCache.put(className, autowiredHelper);\n            }\n        } catch (Exception ex) {\n            blackList.add(className);    \/\/ This instance need not autowired.\n        }\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\u901a\u8fc7\u53cd\u5c04\u5f97\u5230\u8f85\u52a9\u6ce8\u5165\u7c7b CreateNoteActivity$$ARouter$$Autowired \u7684\u5b9e\u4f8b\u540e\u5c31\u8c03\u7528 inject \u65b9\u6cd5\u6ce8\u5165\u5b9e\u4f8b\u3002\u6211\u4eec\u6765\u770b\u4e0b\u8fd9\u4e2a\u7c7b\u7684\u4ee3\u7801\u3002\u5230\u8fd9\u91cc\u5c31\u6c34\u843d\u77f3\u51fa\u4e86\uff0c\u5728\u8df3\u8f6c\u65f6\u5c06\u9700\u8981\u4f20\u9012\u7684\u53c2\u6570\u5199\u5165 postcard \u7684 bundle \u4e2d\uff0c\u7136\u540e\u6210\u529f\u8df3\u8f6c\u5230\u76ee\u6807\u9875\u9762\u540e\u5c31\u53ef\u4ee5\u901a\u8fc7 getIntent \u53d6\u51fa\u53c2\u6570\uff0c\u7136\u540e\u5206\u522b\u7ed9\u76ee\u6807\u9875\u9762\u7684\u6bcf\u4e2a\u9700\u8981\u6ce8\u5165\u7684\u6210\u5458\u53d8\u91cf\u8d4b\u503c\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">public class CreateNoteActivity$ARouter$Autowired implements ISyringe {\n  private SerializationService serializationService;\n\n  @Override\n  public void inject(Object target) {\n    serializationService = ARouter.getInstance().navigation(SerializationService.class);\n    CreateNoteActivity substitute = (CreateNoteActivity)target;\n    substitute.keyName = substitute.getIntent().getStringExtra(\"keyName\");\n    if (null != serializationService) {\n      substitute.mNote = serializationService.parseObject(substitute.getIntent().getStringExtra(\"mNote\"), new com.alibaba.android.arouter.facade.model.TypeWrapper&lt; Note&gt;(){}.getType());\n    } else {\n      Log.e(\"ARouter::\", \"You want automatic inject the field 'mNote' in class 'CreateNoteActivity' , then you should implement 'SerializationService' to support object auto inject!\");\n    }\n  }\n}\n<\/code><\/pre>\n<p><img decoding=\"async\" alt=\"\u56fe\u7247\u63cf\u8ff0\" src=\"http:\/\/121.196.149.88\/home\/docs\/ARouter\/img\/2.png\" style=\"zoom:50%;\"><\/p>\n<h2>@Interceptor \u62e6\u622a\u5668\u4f7f\u7528<\/h2>\n<ul>\n<li>\u62e6\u622a\u5668\u6ce8\u518c<\/li>\n<li>\u62e6\u622a\u5668\u4f7f\u7528\u548c Activity@Route \u5dee\u4e0d\u591a\uff0c\u53ea\u4e0d\u8fc7\u62e6\u622a\u5668\u662f\u4f7f\u7528\u53e6\u5916\u4e00\u4e2a\u6ce8\u89e3 @Interceptor\u3002\u6709\u4e24\u4e2a\u53d8\u91cf\uff0cpriority \u662f\u62e6\u622a\u5668\u7684\u4f18\u5148\u7ea7\uff0c\u503c\u8d8a\u5c0f\u4f18\u5148\u7ea7\u8d8a\u9ad8\uff0c\u4f1a\u4f18\u5148\u62e6\u622a\u3002<\/li>\n<\/ul>\n<pre><code class=\"java\">@Interceptor(priority = 1)\npublic class LoginInterceptor implements IInterceptor {\n    Context mContext;\n    List&lt; String&gt; mNeedLoginActivityList;\n\n    @Override\n    public void process(Postcard postcard, InterceptorCallback callback) {\n        if (mNeedLoginActivityList.contains(postcard.getPath())){\n            if (\"\".equals(SPUtil.getString(\"uId\"))||\n                    SPUtil.getString(\"uId\")==null||\n                    \"\".equals(SPUtil.getString(\"userName\"))||\n                    SPUtil.getString(\"userName\")==null){\n                ToastUtil.show(mContext.getString(R.string.plz_first_login));\n                Log.i(\"binbin\", \"process: \u88ab\u62e6\u622a\u4e86\");\n                callback.onInterrupt(null);\n                ARouter.getInstance().build(Constant.LOGIN_ACTIVITY).navigation();\n            }else{\n                callback.onContinue(postcard);\n            }\n        }else{\n            callback.onContinue(postcard);\n            \/\/postcard.withString(\"extra\", \"\u6211\u662f\u5728\u62e6\u622a\u5668\u4e2d\u9644\u52a0\u7684\u53c2\u6570\");\n            \/\/callback.onContinue(postcard);\n        }\n    }\n\n    @Override\n    public void init(Context context) {\n        this.mContext=context;\n        \/\/\u9700\u8981\u767b\u5f55\u7684\u6d3b\u52a8\n        String[] array={Constant.SS_ACTIVITY};\n        mNeedLoginActivityList= Arrays.asList(array);\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\u62e6\u622a\u5668\u90fd\u9ed8\u8ba4\u5b9e\u73b0 IInterceptor \u63a5\u53e3\uff0c\u5728\u62e6\u622a\u5668\u5b9e\u73b0\u7c7b\u4f7f\u7528\u6ce8\u89e3 @Interceptor \u4f1a\u81ea\u52a8\u6ce8\u518c<\/li>\n<\/ul>\n<pre><code class=\"java\">public interface IInterceptor extends IProvider {\n\n    \/**\n     * The operation of this interceptor.\n     *\n     * @param postcard meta\n     * @param callback cb\n     *\/\n    void process(Postcard postcard, InterceptorCallback callback);\n}\n<\/code><\/pre>\n<h2>\u964d\u7ea7\u7b56\u7565 (\u5b98\u65b9 demo)<\/h2>\n<ul>\n<li>\u964d\u7ea7\u7b56\u7565\u7684\u5b9e\u73b0\u65b9\u5f0f<\/li>\n<li>\u4e00\u3001\u5355\u72ec\u964d\u7ea7 &#8211; \u56de\u8c03\u7684\u65b9\u5f0f<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/xxx\/xxx\").navigation(this, new NavCallback() {\n     @Override\n     public void onFound(Postcard postcard) {\n          Log.d(\"ARouter\", \"\u627e\u5230\u4e86\");\n     }\n\n     @Override\n     public void onLost(Postcard postcard) {\n          Log.d(\"ARouter\", \"\u627e\u4e0d\u5230\u4e86\");\n     }\n\n     @Override\n     public void onArrival(Postcard postcard) {\n          Log.d(\"ARouter\", \"\u8df3\u8f6c\u5b8c\u4e86\");\n     }\n\n     @Override\n      public void onInterrupt(Postcard postcard) {\n           Log.d(\"ARouter\", \"\u88ab\u62e6\u622a\u4e86\");\n      }\n});\n<\/code><\/pre>\n<ul>\n<li>\u4e8c\u3001\u5168\u5c40\u964d\u7ea7 &#8211; \u670d\u52a1\u63a5\u53e3\u7684\u65b9\u5f0f\uff1a<\/li>\n<\/ul>\n<pre><code class=\"java\">ARouter.getInstance().build(\"\/xxx\/xxx\").navigation();\n<\/code><\/pre>\n<ul>\n<li>\u8fd9\u79cd\u65b9\u5f0f\u4ece\u8df3\u8f6c\u4e0a\u770b\u4e0d\u51fa\u6765\uff0c\u4e3b\u8981\u7684\u5904\u7406\u903b\u8f91\u5728\u5185\u90e8\uff0c\u8fd9\u79cd\u964d\u7ea7\u7b56\u7565\u4e3b\u8981\u662f\u5b9e\u73b0\u670d\u52a1\u63a5\u53e3 DegradeService\uff0c\u5c31\u4e00\u4e2a\u65b9\u6cd5\u5c31\u662f onLost<\/li>\n<\/ul>\n<pre><code class=\"java\">public interface DegradeService extends IProvider {\n\n    \/**\n     * Router has lost.\n     *\n     * @param postcard meta\n     *\/\n    void onLost(Context context, Postcard postcard);\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u3010\u7b14\u8bb0\u3011\u3010Android\u3011ARouter \u4ecb\u7ecd \u4e00\u4e2a\u7528\u4e8e\u5e2e\u52a9 Android App \u8fdb\u884c\u7ec4\u4ef6\u5316\u6539\u9020\u7684\u6846\u67b6 \u2014 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,3],"tags":[],"_links":{"self":[{"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/posts\/33"}],"collection":[{"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":0,"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.percy.homes\/index.php\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}