Intent传递对象

Serializable

概述

 对于写代码而言,使用Intent在Activity之间传递对象,最简单的方式就是使被传递对象的类实现Serializable空接口。
Serializable并非Android定义的接口,而是java.io中定义的。

被传递对象类实现Serializable接口

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private double height;
    
    public void setName(String name) {
        this.name=name;
    }
    public void setHeight(double height) {
        this.height=height;
    }
    public String getName() {
        return name;
    }
    public double getHeight() {
        return height;
    }
}

 要注意的是使用Serializable接口必须事先导入java.io.Serializable

传递对象

Person person=new Person();
person.name="Lishaoyin";
person.height="1.70";

Intent intent=new Intent(this,TargetActivity.class);
intent.putExtra("Lishaoyin",person);
startActivity(intent);

 说明:此时用到的putExtra()的版本为:

public Intent putExtra(String name,Serializable value)

特别注意:若被传递对象引用了其它类的对象,被引用对象的类也必须实现Serializable接口!

完整的切换Activity发起方代码

CurrentActivity.java

import...
import java.io.Serializable

public class CurrentActivity extends Activity
                          implements View.OnClickListener {
    
    private Person person=new Person();
                   
    @Override                   
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //load currentActivity.xml
        setContentView(R.layout.currentActivity);  
        
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnClickListener(this);
        
        person.setName("Lishaoyin");
        person.setHeight(1.70);
    }
    
    @Override
    protected onClick(View v) {
        Intent intent=new Intent(this,TargetActivity.class);
        intent.putExtra("Lishaoyin",person);
        startActivity(intent);   //launch TargetActivity
    }
}

Person.java

//implements Serializable interface
public class Person implements Serializable {
    private String name;
    private double height;
    public void setName(String name) {
        this.name=name;
    }
    public void setHeight(double height) {
        this.height=height;
    }
    public String getName() {
        return name;
    }
    public double getHeight() {
        return height;
    }
}

目标Activity接收对象

import...
import java.io.Serializable;

Intent intent=getIntent();
Person person=
      (Person)intent.getSerializableExtra("Lishaoyin");

 注意,这里使用的是getSerializableExtra()方法获取传来的对象,它的定义为:

public Serializable getSerializableExtra(String name)

 它的返回值是Serializable类型,所以要使用它得到的对象,必须对其进行强制类型转换

完整的切换Activity目标方代码

import...
import java.io.Serializable;

public class TargetActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //load targetActivity.xml
        setContentView(R.layout.targetActivity);
        
        Intent intent=getIntent();
        Person person=
              (Person)intent.getSerializableExtra("Lishaoyin");
        
        Toast.makeText(this,person.getName(),LENGTH_SHORT).show();
    }
}

Parcelable

概述

Parcelable接口定义在Parcelable.java中,是Android专用于传递对象的接口。跟Serializable接口一样,若被传递对象引用了其它类的对象,被引用对象的类也必须实现Parcelable接口。

实现步骤

1.实现describeContents()方法,一般直接return 0即可。

@Override
public int describeContents() {
    return 0;  //directly return 0 generally
}

2.实现writeToParcel()方法,在这个方法中将被传递对象中所有需要用到字段都写入Parcel容器从而将对象数据序列化,而不需要的可以不写入。

public void writeToParcel(Parcel dest,int flags) {
    dest.writeString(name);
    dest.writeDouble(height);
    dest.writeInt(weight);
}

 这个方法中使用writeXXX()来向Parcel容器写入基本数据类型以及String类型,需要注意的是没有直接序列化boolean类型的方法,即writeBoolean()是不存在的。如果需要使用boolean类型,就要用其它方式间接实现。


3.创建Creator<?>的实例CREATOR,并且重写其中的两个方法。

public static final Creator<?> CREATOR=new Creator<Person>() {

    @Override
    public Person createFromParcel(Parcel source) {
        Person person=new Person();
        person.name=source.readString();
        person.height=source.readDouble();
        person.weight=source.readInt();
        return person;
    }
    
    @Override
    public Person[] newArray(int size) {
        return new Person[size];
    }
};  //don't forget ";"

Creator<?>是一个泛型接口,其中的<?>表示自动适配类型参数,在上例中创建CREATOR实例时它自动适配Person类。
 重写createFromParcel()中,使用readXXX()方法将对象数据反序列化。特别注意:反序化顺序要与序列化顺序一致,否则将导致数据错乱。例如之前先序列化name,再序列化height最后序列化weight,那么反序列化也必须先反序列化name,再反序列化height,最后反序列化weight
 重写newArray()方法中,一般直接返回new Person[size]即可。


4.使用putExtra()方法传递对象并开启目标Activity。

Person person=new Person();
person.setPerson("Tony Stark",1.78,70);
Intent intent=new Intent();
intent.setClass(this,TargetActivity.class);
intent.putExtra("Tony",person);
startActivity(intent);

 此时用到的putExtra()的版本为:

public Intent putExtra(String name,Parcelable value)

总结

 实现Parcelable接口方式传递对象看上去很复杂难懂,但实际上可以把这个过程视为一个模板,AndroidStudio会自动产生最关键的代码,其余自定义部分自由发挥即可。

完整的Activity切换发起方代码

Person.java

import...

public class Person implements Parcelable {
    private String name;
    private double height;
    private int weight;
    public void setPerson(String name,double height,int weight) {
        this.name=name;
        this.height=height;
        this.weight=weight;
    }
    public String getName() {
        return name;
    }
    public double getHeight() {
        return height;
    }
    public int getWeight() {
        return weight;
    }
    
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest,int flags) {
        dest.writeString(name);
        dest.writeDouble(height);
        dest.writeInt(weight);
    }
    
    public static final Creator<?> CREATOR=new Creator<Person>() {
    
        @Override
        public Person createFromParcel(Parcel source) {
            Person person=new Person();
            person.name=source.readString();
            person.height=source.readDouble();
            person.weight=source.readInt();
            return person;
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }        
    };  //don't forget ";"
}

CurrentActivity.java

import...

public class CurrentActivity extends Activity
                          implements View.OnClickListener {
                          
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //load currentActivity.xml
        setContentView(R.layout.currentActivity);
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        Person person=new Person();
        person.setPerson("Tony Stark",1.78,70);
        
        Intent intent=Intent(this,TargetActivity.class);
        intent.putExtra("Tony",person);
        startActivity(intent);
    }                      
}                          

Activity切换目标方接收对象

Intent intent=getIntent();
Person person=(Person)intent.getParcelableExtra("Tony");

 使用getParcelableExtra()方法,注意进行强制类型转换。

完整的Activity切换目标方代码

TargetActivity.java

import...

public class TargetActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //load targetActivity.xml
        setContentView(R.layout.targetActivity);
        
        TextView tv_1=(TextView)findviewById(R.id.tv_1);
        TextView tv_2=(TextView)findviewById(R.id.tv_2);
        TextView tv_3=(TextView)findviewById(R.id.tv_3);
        
        Intent intent=getIntent();
        Person person=(Person)intent.getParcelableExtra("Tony");
        
        tv_1.setText("姓名:"+person.getName());
        tv_2.setText("身高:"+person.getHeight());
        tv_3.setText("体重:"+person.getWeight());
    }
}

Serializable与Parcelable的简单比较

相同点

 两者都有序列化反序列化操作。

不同点

1.存储媒介Serializable将对象转化为二进制文件,使用IO读写存储在外部存储设备上。Parcelable将对象存储在内存上,直接在内存上进行数据读写。
2.读写速度:由于Parcelable直接在内存上进行数据读写,所以Parcelable的读写速度更快。
3.存储保持Serializable将对象存储在外部设备上,所以使用Serializable可以持久保存对象的当前状态。Parcelable将对象存储在内存上,所以每次重启程序都将丢失对象状态。
3.用途场合Serializable将对象转换成二进制文件,所以可以用于进程之间传递对象、程序向外部存储设备传递对象、程序向网络传递对象。Parcelable用于不需要持久保存对象状态的传递对象场合。

总结

 一般情况下,在Activity之间传递对象不需要持久保存对象状态,所以考虑性能,优先使用Parcelable

比较类型 Serializable Parcelable
存储媒介 外部存储设备 内存
读写速度 一般 较快
存储保持 持久存储 暂时存储

欢迎指正
发布了7 篇原创文章 · 获赞 1 · 访问量 284

猜你喜欢

转载自blog.csdn.net/weixin_42315944/article/details/104937659