前面的注解处理器教程涉及到的 Tieguanyi 框架现在怎么样了?

前不久我录制了一套讲解注解处理器的视频,当中用到了一个叫 “Tieguanyin” 的框架的简化版,这篇文章主要介绍下完整版。

项目是做什么的?

我们遇到了怎样的问题

我们先来看个例子:

 
 
  1. public class UserActivity extends Activity {

  2.    String name;

  3.    int age;

  4.    String title;

  5.    String company;

  6.    ...

  7. }

我们有这样一个 Activity,启动它,我们需要传入四个参数,那么我们通常会怎么做呢?

 
 
  1. Intent intent = new Intent(this, UserActivity.class);

  2. intent.putExtra("age", age);

  3. intent.putExtra("name", name);

  4. intent.putExtra("company", company);

  5. intent.putExtra("title", title);

  6. startActivity(intent);

仅仅是这样,还不够,所以我们还需要在 UserActivity 这个类当中去读取这些值:

 
 
  1. Intent intent = getIntent();

  2. this.age = intent.getIntExtra( "age", 0);

  3. this.name = intent.getStringExtra("name");

  4. this.company = intent.getStringExtra("company" );

  5. this.title = intent.getStringExtra("title");

如果你只有这么一个 Activity 那倒也还好,可是如果你有十个这样的 Activity 呢?

我们怎么去解决

其实我们仔细观察前面的代码,就会发现这两大段传参和读参的代码,都是模式化的代码,我们只需要通过注解处理器来生成就可以了,因此我们给出的解决方法是:

 
 
  1. @Builder

  2. public class UserActivity extends Activity {

  3.    @Required

  4.    String name;

  5.    @Required

  6.    int age;

  7.    @Optional

  8.    String title;

  9.    @Optional

  10.    String company;

  11.    ...

  12. }

这样的话,对于 Java 代码,我们会生成 UserActivityBuilder,通过它启动 UserActivity

 
 
  1. UserActivityBuilder.builder(30, "bennyhuo")

  2.        .company("Kotliner")

  3.        .title("Kotlin Developer")

  4.        .start(this);

注意到,我们的 nameage 都是 Required,因此我们生成的 Builder 在构造时必须对他们进行赋值,而其他两个因为是 Optional,用户可以根据实际情况选择性调用。

而对于 Kotlin 来说,我们则选择为 ContextViewFragment 生成扩展方法,所以我们只需要:

 
 
  1. startUserActivity(30, "bennyhuo", "Kotliner", "Kotlin Developer")

需要注意的是,对于 companytitle 这两个可选的字段,我们的扩展方法提供了默认参数 null,因此我们可以选择性提供这些参数的值:

 
 
  1. startUserActivity(30, "bennyhuo",  title = "Kotlin Developer")

这些方便快捷的方法帮我们处理了 Intent 传递参数的过程,当然,我们也在运行时对 Activity 的声明周期进行了监听,在 ActivityonCreate 方法调用时,对这些参数进行了注入,因此:

 
 
  1. @Override

  2. protected void onCreate(@Nullable Bundle savedInstanceState) {

  3.    super.onCreate(savedInstanceState);

  4.    ...

  5.    nameView.setText(name);

  6.    ...

  7. }

super.onCreate(savedInstanceState); 之后,属性 name 就已经被合理的初始化了。

Fragment 我们也提供了类似的逻辑。

状态保存

在一些特定的场景下,例如转屏时, Activity 或者 Fragment 会被销毁并重新创建,销毁前会调用 onSaveInstanceState 来保存状态。我们同样通过监听其生命周期来实现对用户配置好的属性的值进行保存,以保证这些属性在 Activity 或者 Fragment 重新创建时能够得以恢复。

Activity 转场

除了提供参数传递功能外,还支持通过注解为 Activity 配置 pendingTransition,例如:

 
 
  1. @Builder(pendingTransition = PendingTransition(enterAnim = R.anim.fade_in, exitAnim = R.anim.fade_out))

  2. class UserActivity : AppCompatActivity() {

  3.    ...

  4. }

这样每次启动 UserActivity 时,我们都会在相应的方法当中调用 overridePendingTransition 来设置这些转场动画。

SharedElement 元素动画

从 Android 5.0 开始,系统在 Activity、Fragment、View 之间支持了共享元素动画,但接口使用起来略显复杂,因此我们通过对 Activity 或者 Fragment 添加注解,在启动或者显示相应的组件时,调用相应的方法来实现共享元素动画,让页面的跳转更加连贯。

我们支持用户通过 idtransitionName 来实现元素的关联。

 
 
  1. @Builder(

  2.        sharedElements = [SharedElement(sourceId = R.id.openJavaActivity, targetName = "hello")],

  3.        sharedElementsWithName = [(SharedElementWithName("button2"))],

  4.        sharedElementsByNames= [(SharedElementByNames(source = "button1",target = "button3"))]

  5. )

  6. class DetailsActivity : AppCompatActivity() {

  7.    ...

  8. }

Activity 的结果

有些情况下我们需要目标 Activity 在结束时回传一些结果给当前 Activity,例如我们为了修改用户信息,需要从 UserActivity 跳转到 EditUserActivity,编辑完成之后需要把修改后的结果返回给 UserActivity,我们只需要:

 
 
  1. @Builder(resultTypes = {@ResultEntity(name = "name", type = String.class),

  2.                @ResultEntity(name = "age", type = int.class),

  3.                @ResultEntity(name = "title", type = String.class),

  4.                @ResultEntity(name = "company", type = String.class)})

  5. public class EditUserActivity extends Activity {

  6.    ...

  7. }

这样我们就可以这样启动 EditUserActivity

 
 
  1. EditUserActivityBuilder.builder(30, "Kotlin", "bennyhuo", "Kotlin Developer")

  2.        .start(this, new EditUserActivityBuilder.OnEditUserActivityResultListener() {

  3.            @Override

  4.            public void onResult(int age, String company, String name, String title) {

  5.                ... // handle result

  6.            }

  7.        });

编辑之后这样返回:

 
 
  1. EditUserActivityBuilder.smartFinish(this, 36, "Kotliner","bennyhuo", "Kotlin Dev");

如果是 Kotlin 代码,那么我们还可以使用 Lambda 表达式让代码变得简单:

 
 
  1. startEditUserActivity(36, "Kotliner", "bennyhuo", "Kotlin Dev"){

  2.    age, company, name, title ->  

  3.    ... // handle result

  4. }

值得一提的是,对于在编辑用户信息时, UserActivity 的实例因各种原因(例如开发者选项中的”不保留活动“开启时)被销毁,从 EditUserActivity 返回时, UserActivity 被重新创建,导致之间的回调(匿名内部类、Lambda 表达式)持有的外部引用失效,进而使回调没有意义。为了解决这个问题,我会在页面返回,上一个页面被重新创建时尝试替换掉失效的实例以保证回调可以正常使用,其中主要包括:

  1. 外部 Activity 的实例,这个通常没有问题。

  2. 外部 View 的实例,通常也是回调所在的 Activity 当中的 View,在更新实例时,我们通过 View 的 id 来索引,因此如果布局当中有重复的 id,回调可能将无法更新到正确的实例而产生问题。因此请注意保持 Activity 的布局当中 View 的 id 的唯一性。

  3. 外部 Fragment 的实例,通常也是所在的 Activity 当中的 Fragment,为了保证 Fragment 的唯一性,我使用了 Fragment 未公开的属性 mWho 来进行索引。

尽管从理论的角度,这个更新实例的方法较为可靠,但毕竟这个功能比较 Tricky,如果大家在使用过程中发现回调调用之后没有反应,那么请开 Issue 一起讨论解决方案。

属性名常量

有些情况下,大家在页面跳转时不是很方便调用我们生成的方法,那么这时候为了方便使用,我们也会生成以属性名为值的常量,方便使用,例如:

 
 
  1. public final class UserActivityBuilder {

  2.  public static final String REQUIRED_age = "age";

  3.  public static final String REQUIRED_name = "name";

  4.  public static final String OPTIONAL_company = "company";

  5.  public static final String OPTIONAL_title = "title";

  6.  ...

  7. }

Fragment 支持

由于从 API 28 开始,Android 废弃了 android.app.Fragment 相关的 API,转而推荐使用 support-fragment,同时由于框架本身也需要监听 Fragment 的生命周期,因此我们对于 android.app.Fragment不予支持,请谅解。

项目如何接入?

仓库配置:

 
 
  1. repositories {

  2.    ...

  3.    jcenter()

  4.    ...

  5. }

依赖配置:

 
 
  1. api "com.bennyhuo.tieguanyin:tieguanyin-runtime:$latest_version"

  2. kapt "com.bennyhuo.tieguanyin:tieguanyin-compiler:$latest_version"

如果你不用 Kotlin,那么 kapt 替换成 annotationProcessor。

最后在 ApplicationonCreate 当中调用:

 
 
  1. Tieguanyin.init(this);

即可。

项目状态

  • 当前最新版本 2.0-beta2

  • 当前项目的 compiler 模块已经使用 Kotlin 重构,代码较 1.0 时更紧凑和灵活,部分 Api 也做了一些调整。

  • 为了保证纯 Java 用户的正常使用,runtime 和 annotation 两个模块将一直使用纯 Java 开发。

  • 欢迎大家开 Issue,有空时我就会来迭代一下~

其他相关

  • Apt-Utils:解决了类型在 Java 和 Kotlin 之间的统一性和兼容性问题,提供了注解处理器一些常用的工具方法,尤其适合同时生成 Java 和 Kotlin 代码的注解处理器项目。

  • Apt-Tutorials:基于本项目简化后并录制的一套注解处理器的教学视频。

为什么叫这个名字?

因为我比较喜好喝茶,这个框架开发期间主要喝铁观音。相应的,之前有一段时间常喝茉莉花,在公司内部做了一套框架被我命名为 "Jasmine"。


近期有小伙伴留言没有来得及看到,48小时以后公众平台就不允许回复了,请大家有问题到论坛上提问哈~~


转载请注明出处:微信公众号 Kotlin

640?wx_fmt=jpeg

广告时间

如果你有一定的 Android 基础,恰好还想要深入学习Kotlin,建议留意下我的 Kotlin 新课 “基于 GitHub App 业务深度讲解 Kotlin1.2高级特性与框架设计”。

上线之后,大家普遍反映有难度,有深度,如果哪位朋友想要吊打 Kotlin,不妨来看看哦!

https://coding.imooc.com/class/232.html

640?wx_fmt=jpeg

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值