原创博客,如有转载,请注明出处,非常感谢。
(前置说明,我这里所说的POJO,就是大家认为的POJO去掉了getter/setter)
这里给大家带来的是一个开源项目,托管在github上的:SmartKey,喜欢的同学请给个星星鼓励一下,非常感谢。祝愿大家写代码写得越来越舒畅,下班越来越准时。
在开源世界索取了这么多年,终于第一次往开源界添点小小的砖瓦,甭提有多高兴了,先预览一下demo代码感受一下,你见过这样startActivity的吗?不写key,不写Intent,不写putExtra,不写XXXActivity.class;不写key,不写Intent,不写putExtra,不写XXXActivity.class;不写key,不写Intent,不写putExtra,不写XXXActivity.class;重要的事情我要说三遍,别拦我:
我有一个Activity,名字叫ForResultActivity,跳转到他的时候是这样调用的:
// Demo on how to elegantly passing and receiving extras with intent.
SmartTargets.toForResultActivityATarget()
.params(ForResultReqIBuilder
.newBuilder()
.title(App.getStr(R.string.input_something))
.label(App.getStr(R.string.this_is_label))
.hint(App.getStr(R.string.this_is_hint)))
.goForResult(activity, REQ_CODE_FOR_RESULT);
在目标ForResultActivity里获取传过来的参数(其实是ForResultVM类里,因为Demo里用了最简单原始的MVVM模式)
// Getting values in this very easy way
ForResultReq req = ForResultReqIBuilder.getSmart(activity.getIntent());
** 套路就是SmartTargets出发,to目标,带参数,走起!一个链条一气呵成。 **
以上代码里,SmartTargets类是自动生成的,ForResultReqIBuilder类也是自动生成的!!!你只需要关注你的业务数据,参数究竟怎么放进Intent 的,Intent是哪里创建的,extras的key怎么管理的,目标Activity的class什么时候放进Intent的,或者action,category什么时候放进Intent的,extras取出来又是怎么取的,有完没完啊,这么多问题!!!好了,在这里,这些东西通通不需要关注,真的,你只需要关注你的业务数据,并且,对于已有的代码已有的key管理,你可以保留,这个库直接与原有代码兼容,无痛升级有木有!
好了,啰嗦了这么久,咱们详细说说这个SmartKey吧,首先得从我们最初是怎么进行Activity跳转说起,先讲点历史,忆苦思甜嘛,必须的。相信大家一定走过类似的路。
皇上,您还记得那年大明湖畔的夏雨荷吗?哦,不好意思,大家还记得最初学Android开发的时候怎么启动一个新的Activity吗?来,上代码:
Intent in = new Intent(this, ForResultActivity.class);
in.putExtra("title", App.getStr(R.string.input_something));
in.putExtra("label", App.getStr(R.string.this_is_label));
in.putExtra("hint", App.getStr(R.string.this_is_hint));
startActivityForResult(in, REQ_CODE_FOR_RESULT);
大家还想回到那个年代么?那个年代我想回,但是我不想再写这样的代码了
putExtra这样的模板代码能不能不写?
extra的key能不能不写?看到这样的“Magic Number/String”我就发毛,香菇,蓝瘦。
就算写,这些key从哪里找阿?每次去目标Activity翻么?万一我拷贝的时候拷漏了一个字母怎么办?好害怕啊。我真试过一个"nickName"和"nickname"这样的拼写问题,浪费了不少时间,不要笑,说的就是你。
于是来了第一个升级版(putExtra还是写,毕竟通过Intent传参你只有这么一条路可走):
在ForResultActivity的最头部,我写了以下的代码:
public static final String EXTRA_TITLE = "title";
public static final String EXTRA_LABEL = "label";
public static final String EXTRA_HINT = "hint";
然后启动ForResultActivity的时候变成了:
Intent in = new Intent(this, ForResultActivity.class);
in.putExtra(ForResultActivity.EXTRA_TITLE, App.getStr(R.string.input_something));
in.putExtra(ForResultActivity.EXTRA_LABEL, App.getStr(R.string.this_is_label));
in.putExtra(ForResultActivity.EXTRA_HINT, App.getStr(R.string.this_is_hint));
startActivityForResult(in, REQ_CODE_FOR_RESULT);
拼写错误问题解决了,随着项目的扩大,问题又来了,我在MyActivity,YourActivity,HisActivity等等几个Activity都用到同样的key,我每个Activity都抄一次public static final String EXTRA_XXX吗?相信没谁这么笨的。还有,有些activity的启动是通过action的,天啊,这些通过action跳转的隐式Intent传参key应该放哪里?于是,又一个升级版,这次是集中管理extra的key:
public class MyExtraKeys {
public static final String EXTRA_TITLE = "title";
public static final String EXTRA_LABEL = "label";
public static final String EXTRA_HINT = "hint";
// 更多省略
}
key的问题解决的差不多了,隐式action的问题,这个也好解决,参照前面的MyExtraKeys的做法,我写了一个MyActionUtils类,因为跟上面接近,就不复述了,无非是通过一个相对友好的,容易调用的字段对应到action。
下一步,我相信是很多高级点的工程师喜欢的做法,就是把跳转的方法定义成一个静态的方法,并且把参数组装都放在目标Activity上面,有多种方法的时候,写多个类似的方法:
public static void toForResultActivity(Context from, String title, String label, String hint) {
Intent in = new Intent(from, ForResultActivity.class);
in.putExtra(MyExtraKeys.EXTRA_TITLE, title);
in.putExtra(MyExtraKeys.EXTRA_LABEL, label);
in.putExtra(MyExtraKeys.EXTRA_HINT, hint);
if(!(from instanceof Activity)) {
in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
from.startActivity(in);
}
// 如果还有其他,继续写
一般情况,到这一步,大家也就满意了,然而,对于我,我还是觉得我高兴的太早,因为我的项目终于大到一定程度了,并且也不止我一个人写,由于经过一段时间的积累,也由于对队友的约束不严,技术也在变化,刚才解决的是参数传进来问题,但是还是有各种取出的方法散落在各处,这个时候哪怕一丁点的改动,都需要小心翼翼,什么时候掉进自己挖的坑被埋了都不清楚,于是重构提上日程,既然这些传来传去的参数已经散落在了各自发挥作用的角落,我能不能先把他们集中起来作为重构的第一阶段呢?
于是,有一个升级版的参数传递方案出来了,把参数打包起来传递:
public class ForResultExtras implements Parcelable {
private String title;
private String label;
private String hint;
// getters and setters ...
// Parcelable implementation methods ...
}
这种方式使用就统一了,不再有那么多的key了,因为都是一个类传过来,每个组件都只接收一个自定义的参数,于是MyConstants里面关于参数的key只剩下了:
public static final String EXTRA_KEY = "extra"; // 作为最通用的了
然而,这个方案有天生的问题,既然取出参数的方法原来已经散落各处了,现在要集中起来容易么?特别是我得写多少个类似的Parcelable框架性代码的实现啊?每个集中的类都必须写网parcel里写数据和读数据的方法,还几乎一样的,还要读写顺序一致。当然了,这些都是小问题了,github上搜索一下parceler你就知道了,有人帮你写好了包装,你只要写POJO就行,剩余的框架代码就不需要操心了。然而,集中起来这个问题没办法解决啊,与framework组件、第三方组件不能改的代码怎么打交道啊?这个方案还没真正使用一次,就直接被毙掉了,难道就无解了么?不可能!!!但是自己做之前是不是问问哑巴有没有什么好方案先呢?还真给我找到了一个非常不错的方案:
就是这个文章:用最优雅的方式startActivity
具体就不列出来了,大家自己点开看看,学习一下,人家写的很好,当然,如果他的方案真的解决了我的问题,那么就没有这篇文章了,我写这篇文章是因为他的方案并不能完成我需要解决的问题而已,不是说他写的不好,相反,我觉得相当好也给我不少启发,我的写的方案SmartKey也多少受到他的一些影响,当然,跟他的方案可以说完全不同,先说说为我用上面那个文章说的AutoGo的经验吧,这个库第一眼看到我就眼前一亮,以为终于找到完美的解决方案了,然后翻看源码,不错,着手引入到我的项目里,好了,不到三个钟,我发现很多跟我项目八字不合的问题了,简单说来解决不了的问题有以下,改成疑问的语气来写吧:
- 我原有的代码怎么办?我已经有上百个activity了,与原有方式能共存么?也就是说,我有些extra的获取是散落在各处的,一下子要集中并且取到字段里不容易,由于项目紧,一下子抽不出时间全改怎么办?其实时间是借口,主要问题是原逻辑非常复杂,贸然修改风险大,能缓一下,新写的跳转进来的代码用新的方式写,但是目标activity不改动行么?这个问题没解决。
- 跳转到安卓framework提供的组件,或者第三方库提供的组件,他们的key我改不了,他们的类也是现成的,所以也生成不了方法链,怎么办?这个问题没解决。
- 有些activity我需要用action来跳转,但我也想要用这个便利的方法链该怎么办?一样解决不了,因为他的注解需要写在目标Activity上,用action本来就是为了不明确知道目标Activity的隐式情况的。
- 有些activity的跳转,事先是不知道activity类名的,是根据服务器返回或其他配置值定的,我还是想用这个方法链怎么办?还是没有解决方法,因为跳转链条的开头就在目标Activity。
- AutoGo有代管SharedPreferences的方法,但是不灵活,每个字段必须要注解,并且调用AutoGo.save和AutoGo.restore方法的时候,对应对象的所有被托管的SharedPreferences都会被保存或者获取,我能只保存更改了的那个么?或者只获取我想要的那个么?毕竟多余的执行都是浪费资源啊。其实Intent也有同样的问题,需要把全部用到的需要传递字段注解,并且基本上几个Activity有同样参数的时候,必须写几份,也就是说写的代码不能复用。
- 因为SharedPreferences并没有集中管理,散落在各个使用的角落,key重复了怎么办?有方法自动检测出来么?答案是没办法知道,因为谁也不知道你的key重复是场景需要还是错误。
好吧,自己试试能不能造个轮子,这个轮子需要解决以上所有问题,并且至少要和AutoGo一样用的顺畅,不但Activity的跳转,SharedPreferences的问题也要一并解决了。
于是针对上面的问题,撸起袖子Code,先提前说一说SmartKey的使用套路:
SmartTargets开始,然后调用to目标Activity/Service,然后调用params方法放参数,这个params方法使用的参数类是自动生成的IBuilder类,方法链式调用非常舒畅,然后调用对应的go、goForResult、goWithAction方法或者start方法或者bind方法结尾,整个过程一条链,一气呵成。
- 另外设计一个入口,不再依赖目标Activity上面做改动,这样就避免了改动时必须在跳转开始和目标上都同时要做的问题了,那么,另外的入口通过什么东西来生成比较方便呢?AndroidManifest文件是所有Activity都需要在这里注册的,好,我就从这里入手去生成对应的跳转代码!然后对于extra的问题,我另外用一个POJO来处理这个问题,看代码:
@SmartManifest(manifestPath = "app/src/main/AndroidManifest.xml")
public class App extends Application {
// App的其他代码,
}
根据上面代码,我可以生成一个SmartTargets的类,里面有所有Activity和Service的入口,每当要跳转或者启动Service的时候,就从SmartTargets出发,一直点到目标,另外,再设计了两个toNotDeterminedActivityTarget和toNotDeterminedServiceTarget方法给SmartTargets类,这样,无论怎样的Activity和Service都可以过去了。
对于POJO,以一直作为例子的ForResultActivity为例,我写了两个,一个是为了请求过来的时候传递参数的,一个是为了onActivityResult用的,两个类代码如下:
@SmartIntent
public class ForResultReq {
public String title;
public String label;
public String hint;
}
@SmartIntent
public class ForResultRes {
public String input;
public String input2;
}
然后根据这两个类,APT工具自动生成两个对应的类,ForResultReqIBuilder和ForResultResIBuilder,使用方式就简单了,注意到两个类的注解么?对,只要加上这样的注解,代码就会自动生成,跳转代码(重复一次开头那段代码,_):
SmartTargets.toForResultActivityATarget()
.params(ForResultReqIBuilder
.newBuilder()
.title(App.getStr(R.string.input_something))
.label(App.getStr(R.string.this_is_label))
.hint(App.getStr(R.string.this_is_hint)))
.goForResult(activity, REQ_CODE_FOR_RESULT);
接收参数代码:
ForResultReq req = ForResultReqIBuilder.getSmart(activity.getIntent());
在ForResultActivity的返回时,这样返回:
BackResult
.newBackResult()
.params(ForResultResIBuilder
.newBuilder()
.input(input)
.input2(input2))
.finishWithResult(activity);
BackResult是我设计的另外一个助手类,专门为了在activity返回参数的时候用的,非常的简单舒畅,上面的IBuilder类生成后的代码,看一个吧,连他的接口和父类一并列出了(去掉了注释,请直接看SmartKey):
// 接口,已经写好,不需要关注
public interface IntentKeyMapper {
Intent buildIntent();
}
// 父类,已经写好,有一些比较方便的共用方法可以直接使用,在生成的IBuilder类里使用
public abstract class BaseIntentKeyMapper<B, S> implements IntentKeyMapper {
protected S smart;
public S getSmart() {
return smart;
}
public B replaceSmart(@NonNull S smart) {
if(smart == null)
throw new RuntimeException("Smart wrapper object should not be null.");
this.smart = smart;
return (B) this;
}
public abstract B fillFromSource(Intent source);
public B fillFromSource(Bundle source) {
if (source == null) return (B) this;
return fillFromSource(new Intent().putExtras(source));
}
public Bundle buildBundle() {
return buildIntent().getExtras();
}
}
// 然后就是生成的类了
// req
public final class ForResultReqIBuilder extends BaseIntentKeyMapper<ForResultReqIBuilder, ForResultReq> {
public ForResultReqIBuilder() {
smart = new ForResultReq();
}
public static ForResultReqIBuilder newBuilder() {
return new ForResultReqIBuilder();
}
public static ForResultReqIBuilder newBuilder(ForResultReq fromSource) {
return new ForResultReqIBuilder().replaceSmart(fromSource);
}
public static ForResultReq getSmart(Intent source) {
return new ForResultReqIBuilder().fillFromSource(source).getSmart();
}
public static ForResultReq getSmart(Bundle source) {
return new ForResultReqIBuilder().fillFromSource(source).getSmart();
}
@Override
public Intent buildIntent() {
Intent in = new Intent();
in.putExtra("title", smart.title);
in.putExtra("label", smart.label);
in.putExtra("hint", smart.hint);
return in;
}
public ForResultReqIBuilder fillFromSource(Intent source) {
if (source == null) { return this; }
smart.title = source.getStringExtra("title");
smart.label = source.getStringExtra("label");
smart.hint = source.getStringExtra("hint");
return this;
}
public ForResultReqIBuilder title(String value) {
smart.title = value;
return this;
}
public ForResultReqIBuilder label(String value) {
smart.label = value;
return this;
}
public ForResultReqIBuilder hint(String value) {
smart.hint = value;
return this;
}
}
// res
public final class ForResultResIBuilder extends BaseIntentKeyMapper<ForResultResIBuilder, ForResultRes> {
public ForResultResIBuilder() {
smart = new ForResultRes();
}
public static ForResultResIBuilder newBuilder() {
return new ForResultResIBuilder();
}
public static ForResultResIBuilder newBuilder(ForResultRes fromSource) {
return new ForResultResIBuilder().replaceSmart(fromSource);
}
public static ForResultRes getSmart(Intent source) {
return new ForResultResIBuilder().fillFromSource(source).getSmart();
}
public static ForResultRes getSmart(Bundle source) {
return new ForResultResIBuilder().fillFromSource(source).getSmart();
}
public Intent buildIntent() {
Intent in = new Intent();
in.putExtra("input", smart.input);
in.putExtra("input2", smart.input2);
return in;
}
public ForResultResIBuilder fillFromSource(Intent source) {
if (source == null) { return this; }
smart.input = source.getStringExtra("input");
smart.input2 = source.getStringExtra("input2");
return this;
}
public ForResultResIBuilder input(String value) {
smart.input = value;
return this;
}
public ForResultResIBuilder input2(String value) {
smart.input2 = value;
return this;
}
}
注意,以上所有代码都不需要你写,你只要写你的POJO和使用他们,上面的两个POJO我起名字一个叫ForResultReq, 另外一个是ForResultRes,带上Req和Res的目的是为了自己看方便,表明一个是为了传递数据用的,一个是为返回数据用,参照HTTP请求的做法而已,这里POJO类的起名没有任何要求,只要是Java类,直接使用public字段,对于android,一般情况下,还是这样更省CPU时间和内存资源,能省就省吧,对于一般的POJO,并不存在问题。对于遗留key问题,如果目标activity不想改,那么简单,直接把对应字段标注一下,说明key是啥就行了,比如:
// 标注的字段
@Key(Intent.EXTRA_TEXT)
public String text;
// 对应生成的代码
in.putExtra("android.intent.extra.TEXT", smart.text);
smart.text = source.getStringExtra("android.intent.extra.TEXT");
这样一来目标activity可以不做任何修改,入口可以是全新的了。
- 对于framework或者第三方库的兼容问题,跟前面遗留的key管理一样,只需要一个标注@Key(系统或库提供的key),就这样愉快的兼容了。
- 还是在第1点上说的,你的Action都会在manifest上面声明,所以@SmartManifest(manifestPath = "app/src/main/AndroidManifest.xml")可以知道这些所有信息,直接生成了对应的goWithAction/goForResultWithAction方法。
- NotDeterminedActivityTarge和NotDeterminedServiceTarget两个类专门处理这样的问题,出发点也是SmartTargets,有对应的toNotDeterminedActivityTarge/NotDeterminedServiceTarget方法。
5和6. 对于SharedPreferences,集中管理,并且使用一个POJO类进行配置,java的字段不允许重复,有重复字段直接编译不通过!!!就这样,key重复的问题一定不会出现,并且每个字段有各自的get/set方法,get就是从SharedPreferences获取,set就是保存到SharedPreferences,至于key,忘掉吧,我会另外写一个博客文章专门介绍SharedPreferences的管理,相关的博客文章即将完成了。
说了这么多,咱么开始具体看看SmartKey提供了什么和怎么用吧。由于本人试了一大圈,注册了一大堆帐号,还是未能发布到mavencentral,所以,用起来有点麻烦,需要大家拷贝代码进项目,有成功发布上mavencentral或者jcenter的朋友可以教我一下,非常感谢。
使用方法如下:
第一步,去SmartKey下载源代码。
第二步,拷贝annotation、apt和sdks三个模块到你的项目里
第三步,在根项目的build.gradle添加以下配置到dependencies配置项内:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
第四步,在你的项目下对应的那个主模块的build.gradle下添加以下配置,具体参考下载的代码的app模块:
// 这句放在前面
apply plugin: 'com.neenbedankt.android-apt'
// 这三句放在dependencies配置项内
compile project(':annotation')
compile project(':sdks')
apt project(':apt')
配置就完成了,rebuild一下代码系统就会调用apt工具生成对应的代码。更多内容请参照源码中的app模块,这个模块是一个怎样使用这个库的demo。
下面是具体的使用说明:
annotation模块共有7个注解
@Code注解
这个注解有两个用途,一个用于管理SharedPreferences的时候,有些泛型需要管理的时候标注,另外一个用途是用于标注那些由于继承结构比较复杂,apt工具由于不在android环境下运行,所以并不容易正确生成的代码,例如使用android系统自带的分享功能时,有uri这么一个字段,这个字段用来表示多个文件的路径,类型是ArrayList<Uri>,由于apt工具并不知道uri实现了Parcelable接口,所以生成的代码并不是最好的,可以这样来直接指定生成的代码:
@Key(Intent.EXTRA_STREAM)
@Code(get = "getParcelableArrayListExtra(%1$s)", set = "putParcelableArrayListExtra(%1$s, %2$s)")
public ArrayList<Uri> uri;
上面get表示获取的时候用的代码,%1$s是key的占位符,apt会使用真实的key展开
set表示放进Intent时用的代码,%1$s继续是key的占位符,%2$s是值的占位符,apt会自动匹配真实的值,注意的是,get和set两个值必须同时存在apt才会使用他们,生成代码如下:
smart.uri = source.getParcelableArrayListExtra("android.intent.extra.STREAM");
in.putParcelableArrayListExtra("android.intent.extra.STREAM", smart.uri);
详细例子请参考SmartKey的app模块里面的share包下面的MultiFileShare类,这个类用来描述使用系统自带Intent分享多个图片功能。
@Key注解
这个注解用于指定字段使用的key,一般情况下,新代码根本就不用关注key的问题,这个时候key这个注解就不必要了,当然,如果有遗留代码,又不想改,或者是framework内的比如使用android提供的Intent分享内容,或者使用第三方的库人家的key已经固定了,又或者你就是觉得自己制定的key更好听(起个好字段名不就得了么,默认是直接使用字段名_),就可以用到这个注解了,例如这个用到framework里面现成改不了的key:
// POJO中的用法:
@Key(Intent.EXTRA_EMAIL)
public String[] email;
// 对应生成的代码:
smart.email = (String[]) IntentValueGetter.getValue(source, "android.intent.extra.EMAIL", java.lang.String[].class);
in.putExtra("android.intent.extra.EMAIL", smart.email);
@Required注解
这个注解纯粹给自己看的,在POJO的字段上标识一下,表明这个字段不应该为空,对于这个注解,SmartKey现阶段并不会做任何的处理,目前仅仅为自己看代码服务的。
@SmartIntent注解
用这个注解标注过的POJO类,apt工具会自动扫描所有字段,生成对应的IBuilder类,用于传递数据到目标组件或者从目标组件返回值,属于核心注解,使用SmartKey必用的注解之一,例如前面说到的ForResultReq和ForResultRes类,由于添加了这个注解,所以apt工具为他们生成了ForResultReqIBuilder和ForResultResIBuilder类,直接用这两个builder就可以非常方便的使用方法链传递数据了。
@SmartManifest注解
这个注解一个模块只能出现一次,建议放在对应的主模块,专门用来指定AndroidManifest.xml文件所在的位置,用于生成SmartTargets这个类的,有了这个注解后,apt工具会解析对应的xml文件,把所有activity和service提取出来,生成对应于每一个activity/service的Target描述类,SmartTargets.to方法得到的就是这些生成的Target实例,里面有关于对应activity/service的所有跳转方式方法,是activity跳转/service启动绑定的总入口。
@SmartSharedPreferences注解
这个注解用于集中管理SharedPreferences,具体用法将会用另外一篇文章说明,这里就不详细展开了。
@SmartTarget注解
这个注解用在Activity/Service类上面,目的有两个,一是为了代码阅读的人更轻易的看到目标activity/service用的是哪个POJO作为参数,第二个目的是在前面@SmartManifest注解下生成的对应的Target下,生成一个获取对应POJO的IBuilder实例的方法,例如:
@SmartTarget(req="link.anyauto.smartkey.demo.extras.ForResultReq")
public class ForResultActivity extends BaseActivity {
// 其他activity代码
}
//因为这个注解而生成的代码(在自动生成的你不需要关注的ForResultActivityATarget类里)
public ForResultReqIBuilder newMapperBuilder() {
return ForResultReqIBuilder.newBuilder();
}
// 传参数的时候可以这样获取这个builder
ForResultReqIBuilder builder = SmartTargets.toForResultActivityATarget().newMapperBuilder();
但其实所有activity/service的Target描述类的params方法都不是指定具体Builder类的,可以传递任何的IntentKeyMapper的实现类。
sdk模块下面的一些类的说明:
BackResult类,用于封装activity结束的时候向调用者返回值的细节工作,用法套路:
BackResult.newBackResult()/.newBackResult(resultCode).params(参数).finishWithResult(activity);
跟前面的activity跳转一样样的:
** BackResult出发,带上resultCode和参数,走起! **
OnPrepareIntentCallback接口,这个接口基本上不怎么需要,这个接口在activity Target的go相关方法调用时会被调用,用于给大家一个最后调整Intent的机会。
GsonHelper类,用于包装json与pojo间的相互转换,如果你需要处理一些非标准格式的日期等字段,需要调用他的replaceGson方法替换成你应用需要的gson对象。
其他都是一些基础性代码,可以完全不关注,当然想知道一些原理,看看还是有用的。
对于未确定的Activity目标,比如根据服务器返回的内容进行跳转,或者根据配置进行跳转时,可以这样使用,一样的套路:
SmartTargets.toNotDeterminedActivityTarget()
.activityClass(clz) // 或者 .action(action).addCategories(cats).addCategory(cat)
.params(params)
.go(activity);
关于Activity的跳转,目前还有一些工作在做,就是引入Activity路由,相关工作正在进行中,为了让大家可以非常简单流畅的使用,我会仔细设计,并且融合现有的参数传递方式,我会完善了再commit到github,让大家的跳转更加舒畅,特别是多人协作,根据服务器内容进行跳转时,使用Activity路由将会更加舒畅。
前面说了这么多,实际用法还是建议大家直接参考app这个模块吧,对于程序员,show me the code比啥都管用。写完文章刚好元宵节,祝愿大家元宵快乐,每天准时下班。喜欢的朋友记得在github上给个星星,多谢了。
网友评论