From b8fc9c72fe81cef637a1c06958ffde684b4ee2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A3=E7=BA=AC?= Date: Thu, 16 Mar 2017 19:49:10 +0800 Subject: [PATCH] Add object autowired support. --- README.md | 15 +++++- README_CN.md | 15 +++++- app/src/main/AndroidManifest.xml | 2 +- app/src/main/assets/schame-test.html | 6 +-- .../android/arouter/demo/MainActivity.java | 7 +++ ...ctivity.java => SchemeFilterActivity.java} | 2 +- .../demo/testactivity/Test1Activity.java | 19 ++++++- .../arouter/demo/testinject/TestObj.java | 21 ++++++++ .../demo/testinject/TestParcelable.java | 52 +++++++++++++++++++ arouter-annotation/build.gradle | 2 +- .../arouter/facade/enums/TypeKind.java | 25 +++++++++ .../arouter/facade/model/RouteMeta.java | 44 ++++++++++++++++ arouter-api/build.gradle | 5 +- .../android/arouter/core/LogisticsCenter.java | 46 ++++++++-------- .../android/arouter/facade/Postcard.java | 41 +++++++++++++-- .../alibaba/android/arouter/utils/Consts.java | 16 +++--- arouter-compiler/build.gradle | 4 +- .../processor/AutowiredProcessor.java | 50 ++++++++++++------ .../compiler/processor/RouteProcessor.java | 40 +++++++------- .../arouter/compiler/utils/Consts.java | 1 + .../arouter/compiler/utils/TypeUtils.java | 42 +++++++++++---- gradle.properties | 4 ++ 22 files changed, 364 insertions(+), 95 deletions(-) rename app/src/main/java/com/alibaba/android/arouter/demo/{SchameFilterActivity.java => SchemeFilterActivity.java} (94%) create mode 100644 app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestObj.java create mode 100644 app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestParcelable.java create mode 100644 arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java diff --git a/README.md b/README.md index 65bd7022..e0e37adb 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ ##### [Demo apk下载](http://public.cdn.zhilong.me/app-debug.apk)、[Demo Gif](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-demo.gif) #### 一、功能介绍 -1. **支持直接解析标准URL进行跳转,并自动解析参数注入** +1. **支持直接解析标准URL进行跳转,并自动注入参数到目标页面中** 2. **支持多模块工程使用** 3. **支持添加多个拦截器,自定义拦截顺序** 4. **支持依赖注入,可单独作为依赖注入框架使用** @@ -50,8 +50,10 @@ } dependencies { + // 替换成最新版本, 需要注意的是api + // 要与compiler匹配使用,均使用最新版可以保证兼容 compile 'com.alibaba:arouter-api:x.x.x' - annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' // 替换成最新版本 + annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' ... } // 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4' @@ -82,6 +84,7 @@ ARouter.getInstance().build("/test/1") .withLong("key1", 666L) .withString("key3", "888") + .withObject("key4", new Test("Jack", "Rose")) .navigation(); 5. 添加混淆规则(如果使用了Proguard) @@ -122,6 +125,7 @@ 2. 解析URL中的参数 // 为每一个参数声明一个字段,并使用 @Autowired 标注 + // URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象 @Route(path = "/test/activity") public class Test1Activity extends Activity { @Autowired @@ -130,6 +134,8 @@ int age; @Autowired(name = "girl") // 通过name来映射URL中的不同参数 boolean boy; + @Autowired + TestObj obj; // 支持解析自定义对象,URL中使用json传递 @Override protected void onCreate(Bundle savedInstanceState) { @@ -290,6 +296,11 @@ .build("/home/main") .withFlags(); .navigation(); + + // 对象传递 + ARouter.getInstance() + .withObject("key", new TestObj("Jack", "Rose")) + .navigation(); // 觉得接口不够多,可以直接拿出Bundle赋值 ARouter.getInstance() diff --git a/README_CN.md b/README_CN.md index ae53ab11..a07c833d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -17,7 +17,7 @@ ##### [Demo apk下载](http://public.cdn.zhilong.me/app-debug.apk)、[Demo Gif](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-demo.gif) #### 一、功能介绍 -1. **支持直接解析标准URL进行跳转,并自动解析参数注入** +1. **支持直接解析标准URL进行跳转,并自动注入参数到目标页面中** 2. **支持多模块工程使用** 3. **支持添加多个拦截器,自定义拦截顺序** 4. **支持依赖注入,可单独作为依赖注入框架使用** @@ -48,8 +48,10 @@ } dependencies { + // 替换成最新版本, 需要注意的是api + // 要与compiler匹配使用,均使用最新版可以保证兼容 compile 'com.alibaba:arouter-api:x.x.x' - annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' // 替换成最新版本 + annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' ... } // 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4' @@ -80,6 +82,7 @@ ARouter.getInstance().build("/test/1") .withLong("key1", 666L) .withString("key3", "888") + .withObject("key4", new Test("Jack", "Rose")) .navigation(); 5. 添加混淆规则(如果使用了Proguard) @@ -120,6 +123,7 @@ 2. 解析URL中的参数 // 为每一个参数声明一个字段,并使用 @Autowired 标注 + // URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象 @Route(path = "/test/activity") public class Test1Activity extends Activity { @Autowired @@ -128,6 +132,8 @@ int age; @Autowired(name = "girl") // 通过name来映射URL中的不同参数 boolean boy; + @Autowired + TestObj obj; // 支持解析自定义对象,URL中使用json传递 @Override protected void onCreate(Bundle savedInstanceState) { @@ -288,6 +294,11 @@ .build("/home/main") .withFlags(); .navigation(); + + // 对象传递 + ARouter.getInstance() + .withObject("key", new TestObj("Jack", "Rose")) + .navigation(); // 觉得接口不够多,可以直接拿出Bundle赋值 ARouter.getInstance() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f7dc716f..ca2ff75d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ android:icon="@drawable/ic_launcher" android:label="ARouter demo" android:theme="@style/Base.Theme.AppCompat"> - + diff --git a/app/src/main/assets/schame-test.html b/app/src/main/assets/schame-test.html index f49494c0..b1c79feb 100644 --- a/app/src/main/assets/schame-test.html +++ b/app/src/main/assets/schame-test.html @@ -9,13 +9,13 @@

跳转测试

-

自定义Schame[通常来说都是这样的]

+

自定义Scheme[通常来说都是这样的]

arouter://m.aliyun.com/test/activity1

测试URL Encode情况

-

arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180

+

arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180&obj={"name":"jack","id":"666"}

arouter://m.aliyun.com/test/activity2

arouter://m.aliyun.com/test/activity2?key1=value1

-

(需要开启自动注入)arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180

+

arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180

App Links[防止被App屏蔽]

http://m.aliyun.com/test/activity1

diff --git a/app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java b/app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java index 70895031..f2f2ecf4 100644 --- a/app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java +++ b/app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java @@ -7,6 +7,8 @@ import android.util.Log; import android.view.View; +import com.alibaba.android.arouter.demo.testinject.TestObj; +import com.alibaba.android.arouter.demo.testinject.TestParcelable; import com.alibaba.android.arouter.demo.testservice.HelloService; import com.alibaba.android.arouter.facade.Postcard; import com.alibaba.android.arouter.facade.callback.NavigationCallback; @@ -74,12 +76,17 @@ public void onClick(View v) { .navigation(); break; case R.id.autoInject: + TestParcelable testParcelable = new TestParcelable("jack", 666); + TestObj testObj = new TestObj("Rose", 777); + ARouter.getInstance().build("/test/activity1") .withString("name", "老王") .withInt("age", 18) .withBoolean("boy", true) .withLong("high", 180) .withString("url", "https://a.b.c") + .withParcelable("pac", testParcelable) + .withObject("obj", testObj) .navigation(); break; case R.id.navByName: diff --git a/app/src/main/java/com/alibaba/android/arouter/demo/SchameFilterActivity.java b/app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java similarity index 94% rename from app/src/main/java/com/alibaba/android/arouter/demo/SchameFilterActivity.java rename to app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java index 1f5db9f8..153bcd5c 100644 --- a/app/src/main/java/com/alibaba/android/arouter/demo/SchameFilterActivity.java +++ b/app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java @@ -8,7 +8,7 @@ import com.alibaba.android.arouter.facade.callback.NavigationCallback; import com.alibaba.android.arouter.launcher.ARouter; -public class SchameFilterActivity extends Activity { +public class SchemeFilterActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/app/src/main/java/com/alibaba/android/arouter/demo/testactivity/Test1Activity.java b/app/src/main/java/com/alibaba/android/arouter/demo/testactivity/Test1Activity.java index 991521c8..b5a63f9f 100644 --- a/app/src/main/java/com/alibaba/android/arouter/demo/testactivity/Test1Activity.java +++ b/app/src/main/java/com/alibaba/android/arouter/demo/testactivity/Test1Activity.java @@ -5,6 +5,8 @@ import android.widget.TextView; import com.alibaba.android.arouter.demo.R; +import com.alibaba.android.arouter.demo.testinject.TestObj; +import com.alibaba.android.arouter.demo.testinject.TestParcelable; import com.alibaba.android.arouter.demo.testservice.HelloService; import com.alibaba.android.arouter.facade.annotation.Autowired; import com.alibaba.android.arouter.facade.annotation.Route; @@ -25,6 +27,12 @@ public class Test1Activity extends AppCompatActivity { @Autowired(name = "boy") boolean girl; + @Autowired + TestParcelable pac; + + @Autowired + TestObj obj; + private long high; @Autowired @@ -47,7 +55,16 @@ protected void onCreate(Bundle savedInstanceState) { // high = getIntent().getLongExtra("high", 0); // url = getIntent().getStringExtra("url"); - String params = String.format("name=%s, age=%s, girl=%s, high=%s, url=%s", name, age, girl, high, url); + String params = String.format( + "name=%s,\n age=%s,\n girl=%s,\n high=%s,\n url=%s,\n pac=%s,\n obj=%s", + name, + age, + girl, + high, + url, + pac, + obj + ); helloService.sayHello("Hello moto."); ((TextView)findViewById(R.id.test)).setText("I am " + Test1Activity.class.getName()); diff --git a/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestObj.java b/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestObj.java new file mode 100644 index 00000000..9b14169d --- /dev/null +++ b/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestObj.java @@ -0,0 +1,21 @@ +package com.alibaba.android.arouter.demo.testinject; + +/** + * TODO:Feature + * + * @author zhilong Contact me. + * @version 1.0 + * @since 2017/3/16 下午4:42 + */ +public class TestObj { + public String name; + public int id; + + public TestObj() { + } + + public TestObj(String name, int id) { + this.name = name; + this.id = id; + } +} diff --git a/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestParcelable.java b/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestParcelable.java new file mode 100644 index 00000000..a9df5605 --- /dev/null +++ b/app/src/main/java/com/alibaba/android/arouter/demo/testinject/TestParcelable.java @@ -0,0 +1,52 @@ +package com.alibaba.android.arouter.demo.testinject; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * TODO:Feature + * + * @author zhilong Contact me. + * @version 1.0 + * @since 2017/3/16 下午4:42 + */ +public class TestParcelable implements Parcelable { + public String name; + public int id; + + public TestParcelable() { + } + + public TestParcelable(String name, int id) { + this.name = name; + this.id = id; + } + + protected TestParcelable(Parcel in) { + name = in.readString(); + id = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(name); + dest.writeInt(id); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public TestParcelable createFromParcel(Parcel in) { + return new TestParcelable(in); + } + + @Override + public TestParcelable[] newArray(int size) { + return new TestParcelable[size]; + } + }; +} diff --git a/arouter-annotation/build.gradle b/arouter-annotation/build.gradle index 216b70fb..680a774a 100644 --- a/arouter-annotation/build.gradle +++ b/arouter-annotation/build.gradle @@ -5,7 +5,7 @@ ext { artifact = bintrayName libraryName = 'ARouter annotation' libraryDescription = 'The annotation used in arouter api' - libraryVersion = '1.0.2' + libraryVersion = arouter_annotation_version } compileJava { diff --git a/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java b/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java new file mode 100644 index 00000000..eabe07b0 --- /dev/null +++ b/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java @@ -0,0 +1,25 @@ +package com.alibaba.android.arouter.facade.enums; + +/** + * Kind of field type. + * + * @author Alex Contact me. + * @version 1.0 + * @since 2017-03-16 19:13:38 + */ +public enum TypeKind { + // Base type + BOOLEAN, + BYTE, + SHORT, + INT, + LONG, + CHAR, + FLOAT, + DOUBLE, + + // Other type + STRING, + PARCELABLE, + OBJECT; +} diff --git a/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java b/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java index 9fb91052..9e5f1c42 100644 --- a/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java +++ b/arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java @@ -29,6 +29,14 @@ public RouteMeta() { /** * For versions of 'compiler' less than 1.0.7, contain 1.0.7 + * + * @param type type + * @param destination destination + * @param path path + * @param group group + * @param priority priority + * @param extra extra + * @return this */ public static RouteMeta build(RouteType type, Class destination, String path, String group, int priority, int extra) { return new RouteMeta(type, null, destination, path, group, null, priority, extra); @@ -36,19 +44,55 @@ public static RouteMeta build(RouteType type, Class destination, String path, /** * For versions of 'compiler' greater than 1.0.7 + * + * @param type type + * @param destination destination + * @param path path + * @param group group + * @param paramsType paramsType + * @param priority priority + * @param extra extra + * @return this */ public static RouteMeta build(RouteType type, Class destination, String path, String group, Map paramsType, int priority, int extra) { return new RouteMeta(type, null, destination, path, group, paramsType, priority, extra); } + /** + * Type + * + * @param route route + * @param destination destination + * @param type type + */ public RouteMeta(Route route, Class destination, RouteType type) { this(type, null, destination, route.path(), route.group(), null, route.priority(), route.extras()); } + /** + * Type + * + * @param route route + * @param rawType rawType + * @param type type + * @param paramsType paramsType + */ public RouteMeta(Route route, Element rawType, RouteType type, Map paramsType) { this(type, rawType, null, route.path(), route.group(), paramsType, route.priority(), route.extras()); } + /** + * Type + * + * @param type type + * @param rawType rawType + * @param destination destination + * @param path path + * @param group group + * @param paramsType paramsType + * @param priority priority + * @param extra extra + */ public RouteMeta(RouteType type, Element rawType, Class destination, String path, String group, Map paramsType, int priority, int extra) { this.type = type; this.destination = destination; diff --git a/arouter-api/build.gradle b/arouter-api/build.gradle index 632cd078..41ad2bc6 100644 --- a/arouter-api/build.gradle +++ b/arouter-api/build.gradle @@ -5,7 +5,7 @@ ext { artifact = bintrayName libraryName = 'ARouter sdk' libraryDescription = 'A router for android' - libraryVersion = '1.0.7' + libraryVersion = arouter_api_version } android { @@ -40,7 +40,8 @@ android { dependencies { annotationProcessor 'com.alibaba:arouter-compiler:1.0.3' - compile 'com.alibaba:arouter-annotation:1.0.2' + compile 'com.alibaba:arouter-annotation:1.0.3' + compile 'com.alibaba:fastjson:1.2.9' compile "com.android.support:support-v4:${SUPPORT_LIB_VERSION}" } diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index 93bbd12f..a8ddfd69 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -6,6 +6,7 @@ import com.alibaba.android.arouter.exception.HandlerException; import com.alibaba.android.arouter.exception.NoRouteFoundException; import com.alibaba.android.arouter.facade.Postcard; +import com.alibaba.android.arouter.facade.enums.TypeKind; import com.alibaba.android.arouter.facade.model.RouteMeta; import com.alibaba.android.arouter.facade.template.IInterceptorGroup; import com.alibaba.android.arouter.facade.template.IProvider; @@ -200,31 +201,26 @@ public synchronized static void completion(Postcard postcard) { private static void setValue(Postcard postcard, Integer typeDef, String key, String value) { try { if (null != typeDef) { - switch (typeDef) { - case Consts.DEF_BOOLEAN: - postcard.withBoolean(key, Boolean.parseBoolean(value)); - break; - case Consts.DEF_BYTE: - postcard.withByte(key, Byte.valueOf(value)); - break; - case Consts.DEF_SHORT: - postcard.withShort(key, Short.valueOf(value)); - break; - case Consts.DEF_INT: - postcard.withInt(key, Integer.valueOf(value)); - break; - case Consts.DEF_LONG: - postcard.withLong(key, Long.valueOf(value)); - break; - case Consts.DEF_FLOAT: - postcard.withFloat(key, Float.valueOf(value)); - break; - case Consts.DEF_DOUBLE: - postcard.withDouble(key, Double.valueOf(value)); - break; - case Consts.DEF_STRING: - default: - postcard.withString(key, value); + if (typeDef == TypeKind.BOOLEAN.ordinal()) { + postcard.withBoolean(key, Boolean.parseBoolean(value)); + } else if (typeDef == TypeKind.BYTE.ordinal()) { + postcard.withByte(key, Byte.valueOf(value)); + } else if (typeDef == TypeKind.SHORT.ordinal()) { + postcard.withShort(key, Short.valueOf(value)); + } else if (typeDef == TypeKind.INT.ordinal()) { + postcard.withInt(key, Integer.valueOf(value)); + } else if (typeDef == TypeKind.LONG.ordinal()) { + postcard.withLong(key, Long.valueOf(value)); + } else if (typeDef == TypeKind.FLOAT.ordinal()) { + postcard.withFloat(key, Float.valueOf(value)); + } else if (typeDef == TypeKind.DOUBLE.ordinal()) { + postcard.withDouble(key, Double.valueOf(value)); + } else if (typeDef == TypeKind.STRING.ordinal()) { + postcard.withString(key, value); + } else if (typeDef == TypeKind.PARCELABLE.ordinal()) { + // TODO : How to description parcelable value with string? + } else if (typeDef == TypeKind.OBJECT.ordinal()) { + postcard.withString(key, value); } } else { postcard.withString(key, value); diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java b/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java index d8a4a317..edb642c1 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java @@ -14,6 +14,7 @@ import com.alibaba.android.arouter.facade.model.RouteMeta; import com.alibaba.android.arouter.facade.template.IProvider; import com.alibaba.android.arouter.launcher.ARouter; +import com.alibaba.fastjson.JSON; import java.io.Serializable; import java.lang.annotation.Retention; @@ -210,6 +211,18 @@ public int getFlags() { return flags; } + /** + * Set object value, the value will be convert to string by 'Fastjson' + * + * @param key a String, or null + * @param value a Object, or null + * @return current + */ + public Postcard withObject(@Nullable String key, @Nullable Object value) { + mBundle.putString(key, JSON.toJSONString(value)); + return this; + } + // Follow api copy from #{Bundle} /** @@ -218,6 +231,7 @@ public int getFlags() { * * @param key a String, or null * @param value a String, or null + * @return current */ public Postcard withString(@Nullable String key, @Nullable String value) { mBundle.putString(key, value); @@ -230,6 +244,7 @@ public Postcard withString(@Nullable String key, @Nullable String value) { * * @param key a String, or null * @param value a boolean + * @return current */ public Postcard withBoolean(@Nullable String key, boolean value) { mBundle.putBoolean(key, value); @@ -242,6 +257,7 @@ public Postcard withBoolean(@Nullable String key, boolean value) { * * @param key a String, or null * @param value a short + * @return current */ public Postcard withShort(@Nullable String key, short value) { mBundle.putShort(key, value); @@ -254,6 +270,7 @@ public Postcard withShort(@Nullable String key, short value) { * * @param key a String, or null * @param value an int + * @return current */ public Postcard withInt(@Nullable String key, int value) { mBundle.putInt(key, value); @@ -266,6 +283,7 @@ public Postcard withInt(@Nullable String key, int value) { * * @param key a String, or null * @param value a long + * @return current */ public Postcard withLong(@Nullable String key, long value) { mBundle.putLong(key, value); @@ -278,6 +296,7 @@ public Postcard withLong(@Nullable String key, long value) { * * @param key a String, or null * @param value a double + * @return current */ public Postcard withDouble(@Nullable String key, double value) { mBundle.putDouble(key, value); @@ -290,6 +309,7 @@ public Postcard withDouble(@Nullable String key, double value) { * * @param key a String, or null * @param value a byte + * @return current */ public Postcard withByte(@Nullable String key, byte value) { mBundle.putByte(key, value); @@ -302,6 +322,7 @@ public Postcard withByte(@Nullable String key, byte value) { * * @param key a String, or null * @param value a char + * @return current */ public Postcard withChar(@Nullable String key, char value) { mBundle.putChar(key, value); @@ -314,6 +335,7 @@ public Postcard withChar(@Nullable String key, char value) { * * @param key a String, or null * @param value a float + * @return current */ public Postcard withFloat(@Nullable String key, float value) { mBundle.putFloat(key, value); @@ -326,6 +348,7 @@ public Postcard withFloat(@Nullable String key, float value) { * * @param key a String, or null * @param value a CharSequence, or null + * @return current */ public Postcard withCharSequence(@Nullable String key, @Nullable CharSequence value) { mBundle.putCharSequence(key, value); @@ -338,6 +361,7 @@ public Postcard withCharSequence(@Nullable String key, @Nullable CharSequence va * * @param key a String, or null * @param value a Parcelable object, or null + * @return current */ public Postcard withParcelable(@Nullable String key, @Nullable Parcelable value) { mBundle.putParcelable(key, value); @@ -351,6 +375,7 @@ public Postcard withParcelable(@Nullable String key, @Nullable Parcelable value) * * @param key a String, or null * @param value an array of Parcelable objects, or null + * @return current */ public Postcard withParcelableArray(@Nullable String key, @Nullable Parcelable[] value) { mBundle.putParcelableArray(key, value); @@ -364,6 +389,7 @@ public Postcard withParcelableArray(@Nullable String key, @Nullable Parcelable[] * * @param key a String, or null * @param value an ArrayList of Parcelable objects, or null + * @return current */ public Postcard withParcelableArrayList(@Nullable String key, @Nullable ArrayList value) { mBundle.putParcelableArrayList(key, value); @@ -377,6 +403,7 @@ public Postcard withParcelableArrayList(@Nullable String key, @Nullable ArrayLis * * @param key a String, or null * @param value a SparseArray of Parcelable objects, or null + * @return current */ public Postcard withSparseParcelableArray(@Nullable String key, @Nullable SparseArray value) { mBundle.putSparseParcelableArray(key, value); @@ -389,6 +416,7 @@ public Postcard withSparseParcelableArray(@Nullable String key, @Nullable Sparse * * @param key a String, or null * @param value an ArrayList object, or null + * @return current */ public Postcard withIntegerArrayList(@Nullable String key, @Nullable ArrayList value) { mBundle.putIntegerArrayList(key, value); @@ -401,6 +429,7 @@ public Postcard withIntegerArrayList(@Nullable String key, @Nullable ArrayList value) { mBundle.putStringArrayList(key, value); @@ -413,6 +442,7 @@ public Postcard withStringArrayList(@Nullable String key, @Nullable ArrayList value) { mBundle.putCharSequenceArrayList(key, value); @@ -425,6 +455,7 @@ public Postcard withCharSequenceArrayList(@Nullable String key, @Nullable ArrayL * * @param key a String, or null * @param value a Serializable object, or null + * @return current */ public Postcard withSerializable(@Nullable String key, @Nullable Serializable value) { mBundle.putSerializable(key, value); @@ -437,6 +468,7 @@ public Postcard withSerializable(@Nullable String key, @Nullable Serializable va * * @param key a String, or null * @param value a byte array object, or null + * @return current */ public Postcard withByteArray(@Nullable String key, @Nullable byte[] value) { mBundle.putByteArray(key, value); @@ -449,6 +481,7 @@ public Postcard withByteArray(@Nullable String key, @Nullable byte[] value) { * * @param key a String, or null * @param value a short array object, or null + * @return current */ public Postcard withShortArray(@Nullable String key, @Nullable short[] value) { mBundle.putShortArray(key, value); @@ -461,7 +494,7 @@ public Postcard withShortArray(@Nullable String key, @Nullable short[] value) { * * @param key a String, or null * @param value a char array object, or null - * @return this + * @return current */ public Postcard withCharArray(@Nullable String key, @Nullable char[] value) { mBundle.putCharArray(key, value); @@ -474,7 +507,7 @@ public Postcard withCharArray(@Nullable String key, @Nullable char[] value) { * * @param key a String, or null * @param value a float array object, or null - * @return this + * @return current */ public Postcard withFloatArray(@Nullable String key, @Nullable float[] value) { mBundle.putFloatArray(key, value); @@ -487,7 +520,7 @@ public Postcard withFloatArray(@Nullable String key, @Nullable float[] value) { * * @param key a String, or null * @param value a CharSequence array object, or null - * @return this + * @return current */ public Postcard withCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) { mBundle.putCharSequenceArray(key, value); @@ -500,7 +533,7 @@ public Postcard withCharSequenceArray(@Nullable String key, @Nullable CharSequen * * @param key a String, or null * @param value a Bundle object, or null - * @return this + * @return current */ public Postcard withBundle(@Nullable String key, @Nullable Bundle value) { mBundle.putBundle(key, value); diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java b/arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java index d1a3a482..a1268d97 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java @@ -19,12 +19,12 @@ public final class Consts { public static final String ROUTE_ROOT_PAKCAGE = "com.alibaba.android.arouter.routes"; // Java base type, copy from javax 'TypeKind' - public static final int DEF_BOOLEAN = 0; - public static final int DEF_BYTE = 1; - public static final int DEF_SHORT = 2; - public static final int DEF_INT = 3; - public static final int DEF_LONG = 4; - public static final int DEF_FLOAT = 6; - public static final int DEF_DOUBLE = 7; - public static final int DEF_STRING = 18; + // public static final int DEF_BOOLEAN = 0; + // public static final int DEF_BYTE = 1; + // public static final int DEF_SHORT = 2; + // public static final int DEF_INT = 3; + // public static final int DEF_LONG = 4; + // public static final int DEF_FLOAT = 6; + // public static final int DEF_DOUBLE = 7; + // public static final int DEF_STRING = 18; } diff --git a/arouter-compiler/build.gradle b/arouter-compiler/build.gradle index b1db8d15..84b1ea4f 100644 --- a/arouter-compiler/build.gradle +++ b/arouter-compiler/build.gradle @@ -5,7 +5,7 @@ ext { artifact = bintrayName libraryName = 'ARouter compiler' libraryDescription = 'A compiler for ARouter to find route' - libraryVersion = '1.0.3' + libraryVersion = arouter_compiler_version } compileJava { @@ -14,7 +14,7 @@ compileJava { } dependencies { - compile 'com.alibaba:arouter-annotation:1.0.1' + compile 'com.alibaba:arouter-annotation:1.0.3' compile 'com.google.auto.service:auto-service:1.0-rc2' compile 'com.squareup:javapoet:1.7.0' diff --git a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java index 674b8dc6..0174cd93 100644 --- a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java +++ b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java @@ -4,6 +4,7 @@ import com.alibaba.android.arouter.compiler.utils.Logger; import com.alibaba.android.arouter.compiler.utils.TypeUtils; import com.alibaba.android.arouter.facade.annotation.Autowired; +import com.alibaba.android.arouter.facade.enums.TypeKind; import com.google.auto.service.AutoService; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; @@ -35,7 +36,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; @@ -62,18 +62,23 @@ public class AutowiredProcessor extends AbstractProcessor { private Filer mFiler; // File util, write class file into disk. private Logger logger; - private Types typeUtil; - private Elements elementUtil; + private Types types; + private TypeUtils typeUtils; + private Elements elements; private Map> parentAndChild = new HashMap<>(); // Contain field need autowired and his super class. private static final ClassName ARouterClass = ClassName.get("com.alibaba.android.arouter.launcher", "ARouter"); + private static final ClassName JsonClass = ClassName.get("com.alibaba.fastjson", "JSON"); @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); mFiler = processingEnv.getFiler(); // Generate class. - typeUtil = processingEnv.getTypeUtils(); // Get type utils. - elementUtil = processingEnv.getElementUtils(); // Get class meta. + types = processingEnv.getTypeUtils(); // Get type utils. + elements = processingEnv.getElementUtils(); // Get class meta. + + typeUtils = new TypeUtils(types, elements); + logger = new Logger(processingEnv.getMessager()); // Package the log utils. logger.info(">>> AutowiredProcessor init. <<<"); @@ -97,11 +102,11 @@ public boolean process(Set set, RoundEnvironment roundEnv } private void generateHelper() throws IOException, IllegalAccessException { - TypeElement type_ISyringe = elementUtil.getTypeElement(ISYRINGE); - TypeMirror iProvider = elementUtil.getTypeElement(Consts.IPROVIDER).asType(); - TypeMirror activityTm = elementUtil.getTypeElement(Consts.ACTIVITY).asType(); - TypeMirror fragmentTm = elementUtil.getTypeElement(Consts.FRAGMENT).asType(); - TypeMirror fragmentTmV4 = elementUtil.getTypeElement(Consts.FRAGMENT_V4).asType(); + TypeElement type_ISyringe = elements.getTypeElement(ISYRINGE); + TypeMirror iProvider = elements.getTypeElement(Consts.IPROVIDER).asType(); + TypeMirror activityTm = elements.getTypeElement(Consts.ACTIVITY).asType(); + TypeMirror fragmentTm = elements.getTypeElement(Consts.FRAGMENT).asType(); + TypeMirror fragmentTmV4 = elements.getTypeElement(Consts.FRAGMENT_V4).asType(); // Build input param name. ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build(); @@ -129,7 +134,7 @@ private void generateHelper() throws IOException, IllegalAccessException { for (Element element : childs) { Autowired fieldConfig = element.getAnnotation(Autowired.class); String fieldName = element.getSimpleName().toString(); - if (typeUtil.isSubtype(element.asType(), iProvider)) { // It's provider + if (types.isSubtype(element.asType(), iProvider)) { // It's provider if ("".equals(fieldConfig.name())) { // User has not set service path, then use byType. // Getter @@ -158,17 +163,26 @@ private void generateHelper() throws IOException, IllegalAccessException { } else { // It's normal intent value String statment = "substitute." + fieldName + " = substitute."; boolean isActivity = false; - if (typeUtil.isSubtype(parent.asType(), activityTm)) { // Activity, then use getIntent() + if (types.isSubtype(parent.asType(), activityTm)) { // Activity, then use getIntent() isActivity = true; statment += "getIntent()."; - } else if (typeUtil.isSubtype(parent.asType(), fragmentTm) || typeUtil.isSubtype(parent.asType(), fragmentTmV4)) { // Fragment, then use getArguments() + } else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) { // Fragment, then use getArguments() statment += "getArguments()."; } else { throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!"); } - statment = buildStatement(statment, TypeUtils.typeExchange(element.asType()), isActivity); - injectMethodBuilder.addStatement(statment, StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()); + statment = buildStatement(statment, typeUtils.typeExchange(element), isActivity); + if (statment.startsWith("$T.")) { // Not mortals + injectMethodBuilder.addStatement( + "substitute." + fieldName + " = " + statment, + JsonClass, + (StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()), + ClassName.get(element.asType()) + ); + } else { + injectMethodBuilder.addStatement(statment, StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()); + } // Validater if (fieldConfig.required() && !element.asType().getKind().isPrimitive()) { // Primitive wont be check. @@ -212,8 +226,12 @@ private String buildStatement(String statment, int type, boolean isActivity) { statment += (isActivity ? ("getFloatExtra($S, 0)") : ("getFloat($S)")); } else if (type == TypeKind.DOUBLE.ordinal()) { statment += (isActivity ? ("getDoubleExtra($S, 0)") : ("getDouble($S)")); - } else if (type == TypeKind.OTHER.ordinal()) { + } else if (type == TypeKind.STRING.ordinal()) { statment += (isActivity ? ("getStringExtra($S)") : ("getString($S)")); + } else if (type == TypeKind.PARCELABLE.ordinal()) { + statment += (isActivity ? ("getParcelableExtra($S)") : ("getParcelable($S)")); + } else if (type == TypeKind.OBJECT.ordinal()) { + statment = "$T.parseObject(" + (isActivity ? "substitute.getIntent()." : "getArguments(). ") + "getStringExtra($S), $T.class)"; } return statment; diff --git a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java index f7e3c6b8..6b6a485a 100644 --- a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java +++ b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java @@ -56,6 +56,7 @@ import static com.alibaba.android.arouter.compiler.utils.Consts.NAME_OF_PROVIDER; import static com.alibaba.android.arouter.compiler.utils.Consts.NAME_OF_ROOT; import static com.alibaba.android.arouter.compiler.utils.Consts.PACKAGE_OF_GENERATE_FILE; +import static com.alibaba.android.arouter.compiler.utils.Consts.PARCELABLE; import static com.alibaba.android.arouter.compiler.utils.Consts.SEPARATOR; import static com.alibaba.android.arouter.compiler.utils.Consts.SERVICE; import static com.alibaba.android.arouter.compiler.utils.Consts.WARNING_TIPS; @@ -77,8 +78,9 @@ public class RouteProcessor extends AbstractProcessor { private Map rootMap = new TreeMap<>(); // Map of root metas, used for generate class file in order. private Filer mFiler; // File util, write class file into disk. private Logger logger; - private Types typeUtil; - private Elements elementUtil; + private Types types; + private Elements elements; + private TypeUtils typeUtils; private String moduleName = null; // Module name, maybe its 'app' or others private TypeMirror iProvider = null; @@ -98,8 +100,10 @@ public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); mFiler = processingEnv.getFiler(); // Generate class. - typeUtil = processingEnv.getTypeUtils(); // Get type utils. - elementUtil = processingEnv.getElementUtils(); // Get class meta. + types = processingEnv.getTypeUtils(); // Get type utils. + elements = processingEnv.getElementUtils(); // Get class meta. + + typeUtils = new TypeUtils(types, elements); logger = new Logger(processingEnv.getMessager()); // Package the log utils. // Attempt to get user configuration [moduleName] @@ -122,7 +126,7 @@ public synchronized void init(ProcessingEnvironment processingEnv) { throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log."); } - iProvider = elementUtil.getTypeElement(Consts.IPROVIDER).asType(); + iProvider = elements.getTypeElement(Consts.IPROVIDER).asType(); logger.info(">>> RouteProcessor init. <<<"); } @@ -158,13 +162,13 @@ private void parseRoutes(Set routeElements) throws IOExceptio rootMap.clear(); - // Fantastic four - TypeElement type_Activity = elementUtil.getTypeElement(ACTIVITY); - TypeElement type_Service = elementUtil.getTypeElement(SERVICE); + TypeMirror type_Activity = elements.getTypeElement(ACTIVITY).asType(); + TypeMirror type_Service = elements.getTypeElement(SERVICE).asType(); + TypeElement type_Parcelable = elements.getTypeElement(PARCELABLE); - // Interface of ARouter. - TypeElement type_IRouteGroup = elementUtil.getTypeElement(IROUTE_GROUP); - TypeElement type_IProviderGroup = elementUtil.getTypeElement(IPROVIDER_GROUP); + // Interface of ARouter + TypeElement type_IRouteGroup = elements.getTypeElement(IROUTE_GROUP); + TypeElement type_IProviderGroup = elements.getTypeElement(IPROVIDER_GROUP); ClassName routeMetaCn = ClassName.get(RouteMeta.class); ClassName routeTypeCn = ClassName.get(RouteType.class); @@ -213,23 +217,23 @@ private void parseRoutes(Set routeElements) throws IOExceptio Route route = element.getAnnotation(Route.class); RouteMeta routeMete = null; - if (typeUtil.isSubtype(tm, type_Activity.asType())) { // Activity + if (types.isSubtype(tm, type_Activity)) { // Activity logger.info(">>> Found activity route: " + tm.toString() + " <<<"); // Get all fields annotation by @Autowired Map paramsType = new HashMap<>(); for (Element field : element.getEnclosedElements()) { - if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !typeUtil.isSubtype(field.asType(), iProvider)) { + if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) { // It must be field, then it has annotation, but it not be provider. Autowired paramConfig = field.getAnnotation(Autowired.class); - paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), TypeUtils.typeExchange(field.asType())); + paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field)); } } routeMete = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType); - } else if (typeUtil.isSubtype(tm, iProvider)) { // IProvider + } else if (types.isSubtype(tm, iProvider)) { // IProvider logger.info(">>> Found provider route: " + tm.toString() + " <<<"); routeMete = new RouteMeta(route, element, RouteType.PROVIDER, null); - } else if (typeUtil.isSubtype(tm, type_Service.asType())) { // Service + } else if (types.isSubtype(tm, type_Service)) { // Service logger.info(">>> Found service route: " + tm.toString() + " <<<"); routeMete = new RouteMeta(route, element, RouteType.parse(SERVICE), null); } @@ -261,7 +265,7 @@ private void parseRoutes(Set routeElements) throws IOExceptio case PROVIDER: // Need cache provider's super class List interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces(); for (TypeMirror tm : interfaces) { - if (typeUtil.isSubtype(tm, iProvider)) { + if (types.isSubtype(tm, iProvider)) { // This interface extend the IProvider, so it can be used for mark provider loadIntoMethodOfProviderBuilder.addStatement( "providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))", @@ -338,7 +342,7 @@ private void parseRoutes(Set routeElements) throws IOExceptio JavaFile.builder(PACKAGE_OF_GENERATE_FILE, TypeSpec.classBuilder(rootFileName) .addJavadoc(WARNING_TIPS) - .addSuperinterface(ClassName.get(elementUtil.getTypeElement(ITROUTE_ROOT))) + .addSuperinterface(ClassName.get(elements.getTypeElement(ITROUTE_ROOT))) .addModifiers(PUBLIC) .addMethod(loadIntoMethodOfRootBuilder.build()) .build() diff --git a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java index 4e111b8f..669ebd0d 100644 --- a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java +++ b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java @@ -26,6 +26,7 @@ public class Consts { public static final String FRAGMENT = "android.app.Fragment"; public static final String FRAGMENT_V4 = "android.support.v4.app.Fragment"; public static final String SERVICE = "android.app.Service"; + public static final String PARCELABLE = "android.os.Parcelable"; // Java type private static final String LANG = "java.lang"; diff --git a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java index 7ce7af17..ada41c87 100644 --- a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java +++ b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java @@ -1,7 +1,11 @@ package com.alibaba.android.arouter.compiler.utils; -import javax.lang.model.type.TypeKind; +import com.alibaba.android.arouter.facade.enums.TypeKind; + +import javax.lang.model.element.Element; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import static com.alibaba.android.arouter.compiler.utils.Consts.BOOLEAN; import static com.alibaba.android.arouter.compiler.utils.Consts.BYTE; @@ -9,6 +13,7 @@ import static com.alibaba.android.arouter.compiler.utils.Consts.FLOAT; import static com.alibaba.android.arouter.compiler.utils.Consts.INTEGER; import static com.alibaba.android.arouter.compiler.utils.Consts.LONG; +import static com.alibaba.android.arouter.compiler.utils.Consts.PARCELABLE; import static com.alibaba.android.arouter.compiler.utils.Consts.SHORT; import static com.alibaba.android.arouter.compiler.utils.Consts.STRING; @@ -20,18 +25,33 @@ * @since 2017/2/21 下午1:06 */ public class TypeUtils { + + private Types types; + private Elements elements; + private TypeMirror parcelableType; + + public TypeUtils(Types types, Elements elements) { + this.types = types; + this.elements = elements; + + parcelableType = this.elements.getTypeElement(PARCELABLE).asType(); + } + /** * Diagnostics out the true java type * - * @param rawType Raw type + * @param element Raw type * @return Type class of java */ - public static int typeExchange(TypeMirror rawType) { - if (rawType.getKind().isPrimitive()) { // is java base type - return rawType.getKind().ordinal(); + public int typeExchange(Element element) { + TypeMirror typeMirror = element.asType(); + + // Primitive + if (typeMirror.getKind().isPrimitive()) { + return element.asType().getKind().ordinal(); } - switch (rawType.toString()) { + switch (typeMirror.toString()) { case BYTE: return TypeKind.BYTE.ordinal(); case SHORT: @@ -47,9 +67,13 @@ public static int typeExchange(TypeMirror rawType) { case BOOLEAN: return TypeKind.BOOLEAN.ordinal(); case STRING: - default: - return TypeKind.OTHER.ordinal(); // I say it was java.long.String - + return TypeKind.STRING.ordinal(); + default: // Other side, maybe the PARCELABLE or OBJECT. + if (types.isSubtype(typeMirror, parcelableType)) { // PARCELABLE + return TypeKind.PARCELABLE.ordinal(); + } else { // For others + return TypeKind.OBJECT.ordinal(); + } } } } diff --git a/gradle.properties b/gradle.properties index a880ff65..62597506 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,6 +24,10 @@ SUPPORT_LIB_VERSION=25.2.0 MIN_SDK_VERSION=12 TARGET_SDK_VERSION=25 +arouter_compiler_version=1.0.4 +arouter_api_version=1.0.8 +arouter_annotation_version=1.0.3 + bintrayRepo=maven publishedGroupId=com.alibaba siteUrl=https://github.com/Alibaba/ARouter