Kotlin_01_安卓开发之Intent

Intent就是意图的意思,分两种:显式的(Explicit intent)和隐式的(Implicit intent)。Intent还是很有用的一个好东西,可以帮我们启动活动、发送广播、启动服务等等。但是它并不是这么简单,它还能耍一耍传递数据的花活,除了使用函数直接传递数据,还有序列化传递数据的方法。

基本用法

显式 Intent

按名称(完全限定类名)指定要启动的组件。 通常,知道要启动的 Activity 或服务的类名时,使用显式 Intent 来启动组件。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。

显示调用本质上都是设置Component,从而指定Activity类。常见的用法有:

    //这是最常见的了
    val intent = Intent(MainActivity@this, SecondActivity::class.java)
    startActivity(intent);

    //这个比较能看出本质用法
    val componentName = ComponentName(MainActivity@this, SecondActivity::class.java)
    val intentNewActivity = Intent()
    intentNewActivity.component = componentName
    startActivity(intent)

    //第三种方法
    val intentNewActivity = Intent()
    intentNewActivity.setClass(MainActivity@this, SecondActivity::class.java)
    startActivity(intent)

隐式 Intent

不会指定特定的组件,而是设置Action、Data、Category,让系统来筛选出合适的Activity,从而允许其他应用中的组件来处理它,这会降低程序的耦合度,但效率更低。例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

    //首先,要在AndroidManifest.xml中的application标签中设置如下
    
        
            
            
        
    
    
    //在kotlin文件中编写代码如下
    val intentNewActivity = Intent("android.intent.action.SECOND")

传递简单的数据

比如说,我们可以在某一个活动中定义这样一个intent:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("a string", "hello world");
intent.putExtra("a int", 123);
startActivity(intent);

然后,我们可以在第二个活动这样获取上例中的数据:

getIntent().getStringExtra("a string");
getIntent().getIntExtra("a int", 0);

可以看到,数据传递还是很简单的,也很容易理解,需要说明的时,putExtra函数的参数是以键值对的方式给出的,getIntExtra函数的第二个参数是默认值,也就是不能成功获取数据的时候的函数返回值,可以随便写啦。但是嘞,这种方法传递的数据类型还是很有限的,当我么需要传递自定义的数据类型的时候,就会很捉急!燃鹅不用担心,我们还有更多的技巧用来传递数据。

Serializable方式

Serializable即序列化,意思就是将一个对象转换成可存储或者可传输的状态。具体的实现方法是让一个类去实现Serializable这个接口(import java.io.Serializable)。

//在某一个Activity中定义一个类
class Person : Serializable{
    var name: String = "Baiyuqing"
    var age: Int = 26
}

//在某个跳转函数中传递
val intent = Intent()
intent.setClass(MainActivity@this, SecondActivity::class.java)

val person =  Person()
intent.putExtra("person data", person)
startActivity(intent)

数据的获取也就不一样咯:

val person = intent.getSerializableExtra("person data") as Person
val name:String? = person.name
val age:Int? = person.age

这里调用了getSerializableExtra()函数来获取通过参数传递过来的序列化对象,接着再将它向下转型为Person对象,这样我们就成功实现了利用intent来传递对象的功能啦!

不过,这种方法实际上是使用反射做的,所以效率会略低,并且它会在序列化的过程中,会创建很多临时变量,所以更容易触发GC(垃圾收集)。

Parcelable方式

Parcelable的实现原理是将一个完整的对象进行分解,而分解之后的每一部分都是Intent可以传递的数据类型。

代码实现:

public class Person implements Parcelable {

    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel test, int flags) {
        test.writeString(name);
        test.writeInt(age);
    }
    
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public Person createFromParcel(Parcel source) {
            Person person = new Person();
            person.name = source.readString(); //读取name
            person.age = source.readInt(); //读取age
            return person;
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

}

复杂……好烦……是不是……

但是!这种方法的效率会比前者更高,因为它规则确定、没有将整个对象序列化。烦的是 Parcelable 需要开发者自己去实现序列化的规则。

但是!

在新版的 Kotlin(1.1.4)插件中,已经自动包含了一个自动 Parcelable 实现生成器。简单来说,只需要在主函数中,声明序列化的属性,即添加一个 @Parcelize 注解,它将自动为我们创建 writeToParcel() 和 createFromParcel()。

首先,也是实现接口,然后重写了两个函数describeContents()和writeToParcel()。尤其是第二个函数,要在这里面将类的各个字段一一写出。我们还必须在Person类中提供一个名为CREATE的常量。数据的加载方式不变,具体的获取数据的方法基本一致,只不过换了个名字:

Person person = (Person) getIntent().getParcelableExtra("person data");

你可能感兴趣的:(Kotlin_01_安卓开发之Intent)