Skip to content

Commit

Permalink
Merge pull request alibaba#317 from alibaba/develop
Browse files Browse the repository at this point in the history
Add contributions.
  • Loading branch information
zhi1ong authored Mar 11, 2018
2 parents 02b21a4 + bf94979 commit e81cc81
Show file tree
Hide file tree
Showing 19 changed files with 735 additions and 56 deletions.
49 changes: 40 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

#### 最新版本

模块|arouter-api|arouter-compiler|arouter-annotation
---|---|---|---
最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)
模块|arouter-api|arouter-compiler|arouter-annotation|arouter-register
---|---|---|---|---
最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-register/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-register/_latestVersion)

#### Demo展示

Expand All @@ -31,6 +31,7 @@
10. 支持多种方式配置转场动画
11. 支持获取Fragment
12. 完全支持Kotlin以及混编(配置见文末 其他#5)
13. **支持第三方 App 加固**(使用 arouter-register 实现自动注册)

#### 二、典型应用
1. 从外部URL映射到内部页面,以及参数传递与解析
Expand Down Expand Up @@ -107,6 +108,24 @@ ARouter.getInstance().build("/test/1")
-keep class * implements com.alibaba.android.arouter.facade.template.IProvider
```

6. 使用 Gradle 插件实现路由表的自动加载
```gradle
apply plugin: 'com.alibaba.arouter'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.alibaba:arouter-register:1.0.0"
}
}
```
可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载,默认通过扫描 dex 的方式
进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问
dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 使用!

#### 四、进阶用法
1. 通过URL跳转
``` java
Expand Down Expand Up @@ -508,14 +527,14 @@ dependencies {

首先,Kotlin中的字段是可以自动注入的,但是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin默认会生成set/get方法,并把属性设置为private
所以只要保证Kotlin中字段可见性不是private即可,简单解决可以在字段上添加 @JvmField

6. 通过URL跳转之后,在intent中拿不到参数如何解决?

需要注意的是,如果不使用自动注入,那么可以不写 `ARouter.getInstance().inject(this)`,但是需要取值的字段仍然需要标上 `@Autowired` 注解,因为
只有标上注解之后,ARouter才能知道以哪一种数据类型提取URL中的参数并放入Intent中,这样您才能在intent中获取到对应的参数

7. 新增页面之后,无法跳转?

ARouter加载Dex中的映射文件会有一定耗时,所以ARouter会缓存映射文件,直到新版本升级(版本号或者versionCode变化),而如果是开发版本(ARouter.openDebug()),
ARouter 每次启动都会重新加载映射文件,开发阶段一定要打开 Debug 功能

Expand All @@ -524,9 +543,21 @@ dependencies {
1. 沟通和交流

1. 交流群1 (已满,请加2群)

![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-qq-addr.png)

2. 交流群2

![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG)

![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG)

#### 九、代码贡献 (排名不分先后,时间顺序)

1. [imknown](https://github.com/alibaba/ARouter/commits?author=imknown) : 优化文档格式

2. [crazy1235](https://github.com/crazy1235) : 自动注入支持优先使用默认值

3. [luckybilly](https://github.com/luckybilly) : 通过 Transform API 实现路由表自动注册

4. [LinXiaoTao](https://github.com/LinXiaoTao) : postcard transition support 0

5. [tanglie1993](https://github.com/tanglie1993) : 修正拼写和语法错误
37 changes: 34 additions & 3 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

#### 最新版本

模块|arouter-api|arouter-compiler|arouter-annotation
---|---|---|---
最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)
模块|arouter-api|arouter-compiler|arouter-annotation|arouter-register
---|---|---|---|---
最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-register/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-register/_latestVersion)

#### Demo展示

Expand All @@ -31,6 +31,7 @@
10. 支持多种方式配置转场动画
11. 支持获取Fragment
12. 完全支持Kotlin以及混编(配置见文末 其他#5)
13. **支持第三方 App 加固**(使用 arouter-register 实现自动注册)

#### 二、典型应用
1. 从外部URL映射到内部页面,以及参数传递与解析
Expand Down Expand Up @@ -107,6 +108,24 @@ ARouter.getInstance().build("/test/1")
-keep class * implements com.alibaba.android.arouter.facade.template.IProvider
```

6. 使用 Gradle 插件实现路由表的自动加载
```gradle
apply plugin: 'com.alibaba.arouter'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.alibaba:arouter-register:1.0.0"
}
}
```
可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载,默认通过扫描 dex 的方式
进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问
dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 使用!

#### 四、进阶用法
1. 通过URL跳转
``` java
Expand Down Expand Up @@ -530,3 +549,15 @@ dependencies {
2. 交流群2

![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG)

#### 九、代码贡献 (排名不分先后,时间顺序)

1. [imknown](https://github.com/alibaba/ARouter/commits?author=imknown) : 优化文档格式

2. [crazy1235](https://github.com/crazy1235) : 自动注入支持优先使用默认值

3. [luckybilly](https://github.com/luckybilly) : 通过 Transform API 实现路由表自动注册

4. [LinXiaoTao](https://github.com/LinXiaoTao) : postcard transition support 0

5. [tanglie1993](https://github.com/tanglie1993) : 修正拼写和语法错误
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'com.alibaba.arouter'

android {
compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
import static com.alibaba.android.arouter.utils.Consts.TAG;

/**
* LogisticsCenter contain all of the map.
* LogisticsCenter contains all of the map.
* <p>
* 1. Create instance when it first used.
* 1. Creates instance when it is first used.
* 2. Handler Multi-Module relationship map(*)
* 3. Complex logic to solve duplicate group definition
*
Expand All @@ -52,6 +52,99 @@
public class LogisticsCenter {
private static Context mContext;
static ThreadPoolExecutor executor;
private static boolean registerByPlugin;

/**
* arouter-auto-register plugin will generate code inside this method
* call this method to register all Routers, Interceptors and Providers
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @since 2017-12-06
*/
private static void loadRouterMap() {
registerByPlugin = false;
//auto generate register code by gradle plugin: arouter-auto-register
// looks like below:
// registerRouteRoot(new ARouter..Root..modulejava());
// registerRouteRoot(new ARouter..Root..modulekotlin());
}

/**
* register by class name
* Sacrificing a bit of efficiency to solve
* the problem that the main dex file size is too large
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @param className class name
*/
private static void register(String className) {
if (!TextUtils.isEmpty(className)) {
try {
Class<?> clazz = Class.forName(className);
Object obj = clazz.getConstructor().newInstance();
if (obj instanceof IRouteRoot) {
registerRouteRoot((IRouteRoot) obj);
} else if (obj instanceof IProviderGroup) {
registerProvider((IProviderGroup) obj);
} else if (obj instanceof IInterceptorGroup) {
registerInterceptor((IInterceptorGroup) obj);
} else {
logger.info(TAG, "register failed, class name: " + className
+ " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
}
} catch (Exception e) {
logger.error(TAG,"register class error:" + className);
}
}
}

/**
* method for arouter-auto-register plugin to register Routers
* @param routeRoot IRouteRoot implementation class in the package: com.alibaba.android.arouter.core.routers
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @since 2017-12-06
*/
private static void registerRouteRoot(IRouteRoot routeRoot) {
markRegisteredByPlugin();
if (routeRoot != null) {
routeRoot.loadInto(Warehouse.groupsIndex);
}
}

/**
* method for arouter-auto-register plugin to register Interceptors
* @param interceptorGroup IInterceptorGroup implementation class in the package: com.alibaba.android.arouter.core.routers
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @since 2017-12-06
*/
private static void registerInterceptor(IInterceptorGroup interceptorGroup) {
markRegisteredByPlugin();
if (interceptorGroup != null) {
interceptorGroup.loadInto(Warehouse.interceptorsIndex);
}
}

/**
* method for arouter-auto-register plugin to register Providers
* @param providerGroup IProviderGroup implementation class in the package: com.alibaba.android.arouter.core.routers
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @since 2017-12-06
*/
private static void registerProvider(IProviderGroup providerGroup) {
markRegisteredByPlugin();
if (providerGroup != null) {
providerGroup.loadInto(Warehouse.providersIndex);
}
}

/**
* mark already registered by arouter-auto-register plugin
* @author billy.qi <a href="mailto:[email protected]">Contact me.</a>
* @since 2017-12-06
*/
private static void markRegisteredByPlugin() {
if (!registerByPlugin) {
registerByPlugin = true;
}
}

/**
* LogisticsCenter init, load all metas in memory. Demand initialization
Expand All @@ -62,36 +155,43 @@ public synchronized static void init(Context context, ThreadPoolExecutor tpe) th

try {
long startInit = System.currentTimeMillis();
Set<String> routerMap;

// It will rebuild router map every times when debuggable.
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// These class was generate by arouter-compiler.
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
if (!routerMap.isEmpty()) {
context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
//billy.qi modified at 2017-12-06
//load by plugin first
loadRouterMap();
if (registerByPlugin) {
logger.info(TAG, "Load router map by arouter-auto-register plugin.");
} else {
Set<String> routerMap;

// It will rebuild router map every times when debuggable.
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// These class was generated by arouter-compiler.
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
if (!routerMap.isEmpty()) {
context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
}

PackageUtils.updateVersion(context); // Save new version name when router map update finishes.
} else {
logger.info(TAG, "Load router map from cache.");
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
}

PackageUtils.updateVersion(context); // Save new version name when router map update finish.
} else {
logger.info(TAG, "Load router map from cache.");
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
}
logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
startInit = System.currentTimeMillis();

logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
startInit = System.currentTimeMillis();

for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// Load providerIndex
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// Load providerIndex
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}
}

Expand Down Expand Up @@ -128,7 +228,7 @@ public static Postcard buildProvider(String serviceName) {
/**
* Completion the postcard by route metas
*
* @param postcard Incomplete postcard, should completion by this method.
* @param postcard Incomplete postcard, should complete by this method.
*/
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
Expand Down Expand Up @@ -190,7 +290,7 @@ public synchronized static void completion(Postcard postcard) {

switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must be implememt IProvider
// Its provider, so it must implement IProvider
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
Expand Down Expand Up @@ -267,4 +367,4 @@ private static void setValue(Postcard postcard, Integer typeDef, String key, Str
public static void suspend() {
Warehouse.clear();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public final class Postcard extends RouteMeta {

// Animation
private Bundle optionsCompat; // The transition animation of activity
private int enterAnim;
private int exitAnim;
private int enterAnim = -1;
private int exitAnim = -1;

public Bundle getOptionsBundle() {
return optionsCompat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ public void run() {
ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
}

if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version.
if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version.
((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
}

Expand Down
Loading

0 comments on commit e81cc81

Please sign in to comment.