Activity - 2 传递数据

    xiaoxiao2021-03-25  152

    使用Intent传递数据 Intent传递基本数据类型 向后一个Activity传递数据向前一个Activity返回数据 Intent传递对象 SerializableParcelable 使用全局变量传递数据

    使用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中传递对象?

    在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable类。

    Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

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

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

    实现describeContents方法。内容接口描述,默认返回0就可以;实现writeToParcel方法。将传递的数据打包到Parcel容器中;该实体类必须添加一个常量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); }
    转载请注明原文地址: https://ju.6miu.com/read-22893.html

    最新回复(0)