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

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

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

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

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

    startActivity<LinearLayoutActivity>()

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

import org.jetbrains.anko.startActivity

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

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

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

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

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

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

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

class ActSecondActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_act_second)
val bundle = intent.extras
val request_time = bundle.getString("request_time")
val request_content = bundle.getString("request_content")
tv_response.text = "收到请求消息:\n请求时间为${request_time}\n请求内容为${request_content}"
}
}

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

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

public class MessageInfo implements Parcelable {
public String content;
public String send_time; // 写数据
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(content);
out.writeString(send_time);
} // 例行公事实现createFromParcel和newArray
public static final Parcelable.Creator<MessageInfo> CREATOR
= new Parcelable.Creator<MessageInfo>() {
// 读数据
public MessageInfo createFromParcel(Parcel in) {
MessageInfo info = new MessageInfo();
info.content = in.readString();
info.send_time = in.readString();
return info;
} public MessageInfo[] newArray(int size) {
return new MessageInfo[size];
}
}; @Override
public int describeContents() {
return 0;
}
}

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

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

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

//@Parcelize标记需要设置experimental = true
androidExtensions {
experimental = true
}

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

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

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

class ParcelableSecondActivity : AppCompatActivity() {

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

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

Kotlin入门(21)活动页面的跳转处理的更多相关文章

  1. Kotlin入门教程——目录索引

    Kotlin是谷歌官方认可的Android开发语言,Android Studio从3.0版本开始就内置了Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初Android ...

  2. 写给Android开发者的Kotlin入门

    写给Android开发者的Kotlin入门 转 https://www.jianshu.com/p/bb53cba6c8f4 Google在今年的IO大会上宣布,将Android开发的官方语言更换为K ...

  3. Kotlin入门第二课:集合操作

    测试项目Github地址: KotlinForJava 前文传送: Kotlin入门第一课:从对比Java开始 初次尝试用Kotlin实现Android项目 1. 介绍 作为Kotlin入门的第二课, ...

  4. Kotlin入门(32)网络接口访问

    手机上的资源毕竟有限,为了获取更丰富的信息,就得到辽阔的互联网大海上冲浪.对于App自身,也要经常与服务器交互,以便获取最新的数据显示到界面上.这个客户端与服务端之间的信息交互,基本使用HTTP协议进 ...

  5. Kotlin入门(23)适配器的进阶表达

    前面在介绍列表视图和网格视图时,它们的适配器代码都存在视图持有者ViewHolder,因为Android对列表类视图提供了回收机制,如果某些列表项在屏幕上看不到了,则系统会自动回收相应的视图对象.随着 ...

  6. Kotlin入门(5)字符串及其格式化

    上一篇文章介绍了数组的声明和操作,包括字符串数组的用法.注意到Kotlin的字符串类也叫String,那么String在Java和Kotlin中的用法有哪些差异呢?这便是本文所要阐述的内容了. 首先要 ...

  7. Kotlin入门(9)函数的基本用法

    上一篇文章介绍了Kotlin新增的空安全机制,控制语句部分可算是讲完了,接下来将连续描述Kotlin如何定义和调用函数,本篇文章先介绍函数的基本用法. 前面几篇文章介绍控制语句之时,在setOnCli ...

  8. Kotlin入门(11)江湖绝技之特殊函数

    上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...

  9. Kotlin入门(13)类成员的众生相

    上一篇文章介绍了类的简单定义及其构造方式,当时为了方便观察演示结果,在示例代码的构造函数中直接调用toast提示方法,但实际开发是不能这么干的.合理的做法是外部访问类的成员属性或者成员方法,从而获得处 ...

随机推荐

  1. python高级-面向对象(11)

    一.面向过程和面向对象 面向过程:根据业务逻辑从上到下写代码 面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程 二.类和对象 1.类的概念 面向对象编程的 ...

  2. 【MML】华为MML AAA接口联调,Java版本

    1.我们先设置一些常量数据 package cn.cutter.ztesoft.HuWeiMML.constrant; /** * @description: AAA接口常量设置 * @author: ...

  3. MapReduce实现ReduceSideJoin操作

    本文转载于:http://blog.csdn.net/xyilu/article/details/8996204 一.准备两张表以及对应的数据 (1)m_ys_lab_jointest_a(以下简称表 ...

  4. ElasticSearch入门1: mac 安装

    入门学习顺序: 1. 安装: 1.1 单实例安装: Elastic官方网站: http://www.elastic.co 下载 ElasticSearch: 第一步:点击下载 第二步:点击downlo ...

  5. 课程回顾-Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization

    训练.验证.测试划分的量要保证数据来自一个分布偏差方差分析如果存在high bias如果存在high variance正则化正则化减少过拟合的intuitionDropoutdropout分析其它正则 ...

  6. 关于 Kubernetes 中的 Volume 与 GlusterFS 分布式存储

    容器中持久化的文件生命周期是短暂的,如果容器中程序崩溃宕机,kubelet 就会重新启动,容器中的文件将会丢失,所以对于有状态的应用容器中持久化存储是至关重要的一个环节:另外很多时候一个 Pod 中可 ...

  7. 解决java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList的问题

    一.背景 最近闲来无事,想自己搭建一套Spring+SpringMVC+Mybatis+Mysql的环境(搭建步骤会在以后博客中给出),结果运行程序时,适用@ResponseBody注解进行返回Lis ...

  8. Vagrant挂载目录失败mount: unknown filesystem type ‘vboxsf’

    一.背景 ​ 最近在玩Mac OS下的虚拟机,然后有朋友推荐了我Vagrant,但是在设置完跟宿主机共享目录然后启动虚拟机的时候,出现了vagrant mount: unknown filesyste ...

  9. MFC原理第二讲.MFC的初始化过程

    MFC原理第二讲MFC的初始化过程 一丶简介 通过上一讲.我们手工模拟了一个MFC程序. 但是上一讲留下了疑问. 就是WinMain在哪.以及消息处理在哪里. 这一节主要就是讲解Winmain在哪里. ...

  10. 基于saltstack自动化部署高可用kubernetes集群

    SaltStack自动化部署HA-Kubernetes 本项目在GitHub上,会不定期更新,大家也可以提交ISSUE,地址为:https://github.com/skymyyang/salt-k8 ...