Activity - 2 传递数据

使用Intent传递数据

在启动活动时传递数据的思路很简单,Intent 中提供了一系列 putExtra()方法的重载,可 以把我们想要传递的数据暂存在 Intent 中,启动了另一个活动后,只需要把这些数据再从 Intent 中取出就可以了。

Intent传递基本数据类型

向后一个Activity传递数据

通过 putExtra()方法传递 了一个字符串。注意这里 putExtra()方法接收两个参数,第一个参数是键,用于后面从 Intent 中取值,第二个参数才是真正要传递的数据。

String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 
intent.putExtra("extra_data", data);
startActivity(intent);

可以通过 getIntent()方法获取到用于启动 SecondActivity 的 Intent,然后调用 getStringExtra()方法,传入相应的键值,就可以得到传递的数据了。这里由于我们传递的是 字符串,所以使用 getStringExtra()方法来获取传递的数据,如果传递的是整型数据,则使用 getIntExtra()方法,传递的是布尔型数据,则使用 getBooleanExtra()方法,以此类推。

Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");

向前一个Activity返回数据

Activity中有一个startActivityForResult() 方法也是用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活动。startActivityForResult()方法接收两个参数,第一个参数还是 Intent,第二个参数是请求码,用于在之后的回调中判断数据的来源。

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);

返回数据到前一个Activity时也是通过Intent,只不过这个 Intent 仅仅是用于传递数据而已, 它没有指定任何的“意图”。紧接着把要传递的数据存放在 Intent 中,然后调用了 setResult() 方法。这个方法非常重要,是专门用于向上一个活动返回数据的。setResult()方法接收两个 参数,第一个参数用于向上一个活动返回处理结果,一般只使用 RESULT_OK 或 RESULT_CANCELED 这两个值,第二个参数则是把带有数据的 Intent 传递回去,然后调用 了 finish()方法来销毁当前活动。

Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();

由于我们是使用 startActivityForResult()方法来启动 SecondActivity 的,在 SecondActivity 被销毁之后会回调上一个活动的 onActivityResult()方法,因此我们需要在 FirstActivity 中重 写这个方法来得到返回的数据。onActivityResult()方法带有三个参数,第一个参数 requestCode,即我们在启动活动时传 入的请求码。第二个参数 resultCode,即我们在返回数据时传入的处理结果。第三个参数 data, 即携带着返回数据的 Intent。由于在一个活动中有可能调用 startActivityForResult()方法去启 动很多不同的活动,每一个活动返回的数据都会回调到 onActivityResult()这个方法中,因此 我们首先要做的就是通过检查 requestCode 的值来判断数据来源。确定数据是从SecondActivity 返回的之后,我们再通过 resultCode 的值来判断处理结果是否成功。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK) {
                String returnedData = data.getStringExtra("data_return");
                Log.d("FirstActivity", returnedData);
            }
            break;
        default:
} }

Intent传递对象

使用 Intent 来传递对象通常有两种实现方式,Serializable 和 Parcelable。

Serializable

为什么要将对象序列化?
1、永久性保存对象,保存对象的字节序列到本地文件中;
2、用过序列化对象在网络中传递对象;
3、通过序列化对象在进程间传递对象。
Serializable的作用是将数据对象存入字节流当中,在需要时重新生成对象,主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
implements Serializable接口的的作用就是给对象打了一个标记,系统会自动将其序列化。

要传递的对象类:
public class Person implements Serializable { 
    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; 
    } 
}
第一个Activity
Person person = new Person();
person.setAge(18);
person.setName("Nick");
Intent intent = new Intent(this,Second.class);
intent.putExtra("person data",person);
startActivity(intent);
第二个Activity
Intent intent = getIntent();
Person person = (Person) intent.getSerializableExtra("person data");
TextView textView = (TextView)findViewById(R.id.textView);
textView.setText("name :" + person.getName() + "   age:"+person.getAge());

Parcelable

为什么要实现Parfcelable接口来实现在Intent中传递对象?

  1. 在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable类。
  2. Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

    注意:Parcelable不能使用在将数据存储在磁盘上的情况,因为Parcelable不能很好的保存数据的持续性在外界有变化的情况下。因此在这种情况下,建议使用Serializable

Parcel类
就应用程序而言,在常使用Parcel类的场景就是在Activity间传递数据。在Activity间使用Intent传递数据的时候,可以通过Parcelable机制传递复杂的对象。
Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都 是 Intent 所支持的数据类型,这样也就实现传递对象的功能了。
实现Parcel类步骤:

  1. 实现describeContents方法。内容接口描述,默认返回0就可以;
  2. 实现writeToParcel方法。将传递的数据打包到Parcel容器中;
  3. 该实体类必须添加一个常量CREATOR(名字大小写都不能使其他的),该常量必须实现Parcelable的内部接口:Parcelable.Creator,并实现该接口中的两个方法。
public class Person implements Parcelable{
    private String name;
    private int age;

    public void setName(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        //该方法将类的数据写入外部提供的Parcel中.即打包需要传递的数据到Parcel容器保存,以便从parcel容器获取数据  
        dest.writeString(name);
        dest.writeInt(age);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
        @Override
        public Person createFromParcel(Parcel source) {
            //从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。
            Person person = new Person();
            person.name = source.readString();
            person.age = source.readInt();
            return person;
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

简化Parcel操作
如果你使用android Studio可以通过安装android-parcelable-intellij-plugin插件,或者自己配置模板进行操作。

parceler
除了上面的操作,还有大量的第三方库来简化Parcelable操作。当然使用这些库也许会降低Parcelable的性能。Parceler就是这样一个库。

Parceler使用非常简单,在定义Model时用@Parcel进行注解,在传递数据的时候使用Parcels的wrap方法来包装成一个Parcelable对象。获取数据时用Parcels的unwrap方法来获取对象。

使用Parceler库

//引入Parceler库
compile "org.parceler:parceler-api:1.0.4"
annotationProcessor "org.parceler:parceler:1.0.4"

//用@Parcel注解model类
@Parcel
public class people{
    String name;
    int age;

    public people(){ /*Required empty bean constructor*/ }

    public people(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String getName() { return name; }

    public int getAge() { return age; }
}


//把model类打包到parcelable中
Parcelable parcel = Parcels.wrap(people);
bundle.putParcelable("abc",parcel);


//把model类从parcelable中取出
Parcelable parcelable = bundle.getParcelable("abc");
people people = Parcels.unwrap(parcelable);

使用全局变量传递数据

Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。

<application
        android:name=".MyApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
    </application>

android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。

基本思路是这样的。在Application中创建一个HashMap<String,Object> ,以字符串为索引,Object为value这样我们的HashMap就可以存储任何类型的对象了。在Activity A中把需要传递的对象放入这个HashMap,然后通过Intent或者其它途经再把这人索引的字符串传递给Activity B ,Activity B 就可以根据这个字符串在HashMap中取出这个对象了。只要再向下转个型 ,就实现了对象的传递。

public class MyApp extends Application{
    private Map<String,Object> globalData;

    @Override
    public void onCreate() {
        super.onCreate();
        globalData = new HashMap<String, Object>();
    }

    public Object getGlobalData(String key){
        return globalData.get(key);
    }

    public void addGlobalData(String key, Object value){
        globalData.put(key, value);
    }

    public void removeGlobalData(String key)
    {
        globalData.remove(key);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        globalData.clear();
    }
}

记得数据传递完成之后,把存放在application的HashMap中的数据remove掉,以免发生内存的泄漏。

FirstActivity:

Intent intent = new Intent(this,Main2Activity.class);
String userCode = "nick18";
intent.putExtra("main",userCode);
MyApp myApp = (MyApp)getApplication();
User user = new User();
user.age = 18;
user.name = "nick";
myApp.addGlobalData(userCode,user);
startActivity(intent);

SecondActivity:

Intent intent = getIntent();
String userCode = intent.getStringExtra("main");
MyApp myApp = (MyApp) getApplication();
User user = (User) myApp.getGlobalData(userCode);
if (user != null) {
    Log.d("t", "name :" + user.name + "   age :" + user.age);
    myApp.removeGlobalData(userCode);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值