经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Kotlin入门(21)活动页面的跳转处理
来源:cnblogs  作者:aqi00  时间:2018/10/8 9:04:53  对本文有异议

Activity的活动页面跳转是App最常用的功能之一,在前几章的demo源码中便多次见到了,常常是点击界面上的某个按钮,然后跳转到与之对应的下一个页面。对于App开发者来说,该功能的实现非常普通,使用Java编码不过以下两行代码而已:

  1. Intent intent = new Intent(MainActivity.this, LinearLayoutActivity.class);
  2. startActivity(intent);

 

上面代码的关键之处在于Intent的构造函数,其中第一个参数指定了页面跳转动作的来源,即MainActivity这个源页面,MainActivity.this通常简写为this;构造Intent的第二个参数则表示页面跳转动作的目的地,即LinearLayoutActivity这个目标页面。倘若把这两行Java代码转换为Kotlin代码(复制这两行然后粘贴到kt文件中,Android Studio就会自动完成转换),则可看到活动跳转的Kotlin代码如下所示:

  1. val intent = Intent(this@MainActivity, LinearLayoutActivity::class.java)
  2. startActivity(intent)

 

对比之下,这里的Kotlin代码与Java代码主要有两点不同之处:
1、在类内部指代自身的this关键字,Java的完整写法是“类名.this”,而Kotlin的完整写法是“this@类名”,当然二者均可简写为“this”;
2、获取某个类的class对象,Java的写法是“类名.class”,而Kotlin的写法是“类名::class.java”,一看便知带有浓浓的Java风味;
看起来,Kotlin代码与Java代码半斤八两,未有明显的简化,令人产生小小的失望。但细心的读者也许已经注意到了,本书附录源码里的活动跳转,并非上述的Kotlin正宗写法,而是下面这种简化版的写法:

  1. startActivity<LinearLayoutActivity>()

 

究其原因,乃是Anko库利用Kotlin的扩展函数,给Context类新增了名为startActivity的新方法。故而使用简化版的写法之前,必须先导入Anko库的指定文件,即在kt文件头部添加下面一行导入语句:

  1. import org.jetbrains.anko.startActivity

 

活动页面跳转的时候,往往还要携带一些请求参数,如果使用Java编码,可以很轻松地调用Intent对象的putExtra方法,通过“putExtra(参数名, 参数值)”的方式传递消息,就像下面代码那样:

  1. Intent intent = new Intent(this, ActSecondActivity.class);
  2. intent.putExtra("request_time", DateUtil.getNowTime());
  3. intent.putExtra("request_content", et_request.getText().toString());
  4. startActivity(intent);

 

如果使用Anko的简化写法,其实也很容易,只要在startActivity后面的括号中依次填上每个参数字段的字段名和字段值,具体的Kotlin跳转代码如下所示:

  1. //第一种写法,参数名和参数值使用关键字to隔开
  2. startActivity<ActSecondActivity>(
  3. "request_time" to DateUtil.nowTime,
  4. "request_content" to et_request.text.toString())

 

注意到上面的写法使用关键字to隔开参数名和参数值,感觉不够美观,而且容易使人迷惑,to后面究竟要跟着字段名还是字段值呢?所以Anko库提供了另一种符合习惯的写法,也就是利用Pair类把参数名和参数值进行配对,Pair的第一个参数为字段名,第二个参数为字段值。据此改写后的Kotlin跳转代码如下所示:

  1. //第二种写法,利用Pair把参数名和参数值进行配对
  2. startActivity<ActSecondActivity>(
  3. Pair("request_time", DateUtil.nowTime),
  4. Pair("request_content", et_request.text.toString()))

 

不管哪种写法,在下一个活动中解析请求参数的方式都一样,都得先获取Bundle对象,然后分别根据字段名称获取对应的字段值。具体的请求参数解析代码如下所示:

  1. class ActSecondActivity : AppCompatActivity() {
  2.  
  3. override fun onCreate(savedInstanceState: Bundle?) {
  4. super.onCreate(savedInstanceState)
  5. setContentView(R.layout.activity_act_second)
  6. val bundle = intent.extras
  7. val request_time = bundle.getString("request_time")
  8. val request_content = bundle.getString("request_content")
  9. tv_response.text = "收到请求消息:\n请求时间为${request_time}\n请求内容为${request_content}"
  10. }
  11. }

下面通过测试界面观察一下消息数据发送之前和发送之后的效果,如下面左图所示,这时第一个页面准备跳转到第二个页面;如下面右图所示,这是跳转后的第二个页面,界面上展示了第一个页面传递过来的参数信息。

Activity之间传递的参数类型,除了整型、浮点数、字符串等基本数据类型,还允许传递序列化结构如Parcelable对象。这个Parcelable对象可不是简单的实体类,而是实现了Parcelable接口的实体类,实现接口意味着该类必须重写接口定义的所有方法,不管你愿不愿意都得老老实实地照猫画虎。譬如前面的活动跳转传递了两个字段数据,如果把这两个字段放到Parcelable对象中,仅仅包含两个字段的Parcelable类对应的Java代码也如下面这般冗长:

  1. public class MessageInfo implements Parcelable {
  2. public String content;
  3. public String send_time;
  4.  
  5. // 写数据
  6. @Override
  7. public void writeToParcel(Parcel out, int flags) {
  8. out.writeString(content);
  9. out.writeString(send_time);
  10. }
  11.  
  12. // 例行公事实现createFromParcel和newArray
  13. public static final Parcelable.Creator<MessageInfo> CREATOR
  14. = new Parcelable.Creator<MessageInfo>() {
  15. // 读数据
  16. public MessageInfo createFromParcel(Parcel in) {
  17. MessageInfo info = new MessageInfo();
  18. info.content = in.readString();
  19. info.send_time = in.readString();
  20. return info;
  21. }
  22.  
  23. public MessageInfo[] newArray(int size) {
  24. return new MessageInfo[size];
  25. }
  26. };
  27.  
  28. @Override
  29. public int describeContents() {
  30. return 0;
  31. }
  32. }

看看这架势,如此简单的自定义Parcelable类,就得重写包括writeToParcel、createFromParcel、newArray、describeContents在内的四个方法,可谓是兴师动众。由此可见这里又是Java的一个痛点,正适合Kotlin施展拳脚、好好改进。在第五章的类和对象中,介绍了Kotlin对数据类的写法,在类名前面关键字data,Kotlin即可自动提供get/set、equals、copy、toString等诸多方法。那么序列化对象的改造也相当简单,仅需在类名之前增加一行注解“@Parcelize”就好了,整个类的Kotlin代码只有下面寥寥几行:

  1. @Parcelize
  2. data class MessageInfo(val content: String, val send_time: String) : Parcelable {
  3. }

 

不过若想正常编译,还需修改模块的编译文件build.gradle,在文件末尾添加下面几行,表示增加安卓插件的编译支持:

  1. //@Parcelize标记需要设置experimental = true
  2. androidExtensions {
  3. experimental = true
  4. }

 

编译文件修改完毕,现在能在Kotlin中使用序列化对象的注解了。虽然自定义的MessageInfo类内部没有任何一行代码,但是它除了具备数据类的所有方法,也自动实现了Parcelable接口的几个方法。接下来就可以利用该类传输活动跳转的序列化数据了,下面是改写后的Kotlin跳转代码:

  1. val request = MessageInfo(et_request.text.toString(), DateUtil.nowTime)
  2. startActivity<ParcelableSecondActivity>("message" to request)

 

跳转后的下一个页面,调用getParcelable即可正常获得原始的序列化数据,具体的数据解析代码如下所示:

  1. class ParcelableSecondActivity : AppCompatActivity() {
  2.  
  3. override fun onCreate(savedInstanceState: Bundle?) {
  4. super.onCreate(savedInstanceState)
  5. setContentView(R.layout.activity_parcelable_second)
  6. val request = intent.extras.getParcelable<MessageInfo>("message")
  7. tv_response.text = "收到打包好的请求消息:\n请求时间为${request.send_time}\n请求内容为${request.content}"
  8. }
  9. }

同样通过测试界面观察序列化对象的打包和解包效果,如下面左图所示,这时第一个页面准备跳转到第二个页面;如下面右图所示,这是跳转后的第二个页面,界面上展示了第一个页面传递过来的序列化数据。

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号