Android Inten传递对象

Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务、以及发送广播等场景。

intent传递数据

一、简单的传递数据

单个及多个数据传递:


image.png
二、传递数组
intent.putStringArray("StringArray", new String[]{"1111","222"});
//可把StringArray换成其他数据类型,比如int,float等等..

读取数组:

String[] str = bd.getStringArray("StringArray")
三、传递集合

(1)List<基本数据类型或String>

intent.putStringArrayListExtra(name, value)
intent.putIntegerArrayListExtra(name, value)

读取集合:

intent.getStringArrayListExtra(name)
intent.getIntegerArrayListExtra(name)

(2)List

将list强转成Serializable类型,然后传入(可用Bundle做媒介)
写入集合:

 putExtras(key, (Serializable)list)

读取集合

(List) getIntent().getSerializable(key)
 
 

PS:Object类需要实现Serializable接口

(3)Map,或更复杂的
解决方案:外层套个List

//传递复杂些的参数 
Map map1 = new HashMap();  
map1.put("key1", "value1");  
map1.put("key2", "value2");  
List> list = new ArrayList>();  
list.add(map1);  

 Intent intent = new Intent();  
 intent.setClass(MainActivity.this,ComplexActivity.class);  
 Bundle bundle = new Bundle();  

//须定义一个list用于在budnle中传递需要传递的ArrayList,这个是必须要的  
ArrayList bundlelist = new ArrayList();   
bundlelist.add(list);   
bundle.putParcelableArrayList("list",bundlelist);  
intent.putExtras(bundle);                
startActivity(intent); 
 
 

四、Intent传递对象

传递对象的方式有两种:将对象转换为Json字符串或者通过Serializable,Parcelable序列化 不建议使用Android内置的抠脚Json解析器,可使用fastjson或者Gson第三方库!

(1)将对象转换为Json字符串

Gson解析
Model:

public class Book{
private int id;
private String title;
//...
}

public class Author{
private int id;
private String name;
//...
}

写入数据:

Book book=new Book();
book.setTitle("Java编程思想");
Author author=new Author();
author.setId(1);
author.setName("Bruce Eckel");
book.setAuthor(author);
Intent intent=new                   
Intent(this,SecondActivity.class);
intent.putExtra("book",new Gson().toJson(book));
startActivity(intent);

读取数据:

String bookJson=getIntent().getStringExtra("book");
Book book=new Gson().fromJson(bookJson,Book.class);
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());
(2)使用Serializable,Parcelable序列化对象

但是不知道你有没有发现,putExtra()方法中所支持的数据类型是有限的,虽然常用的一些数据类型它都会支持,但是当你想去传递一些自定义对象的时候就会发现无从下手。不用担心,下面我们就学习一下使用Intent 来传递对象的技巧。

方式一:Serializable 方式
Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。至于序列化的方法也很简单,只需要让一个类去实现Serializable 这个接口就可以了。
比如说有一个Person 类,其中包含了name 和age 这两个字段,想要将它序列化就可以这样写:

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;  
  }  
}  

其中get、set 方法都是用于赋值和读取字段数据的,最重要的部分是在第一行。这里让Person 类去实现了Serializable 接口,这样所有的Person 对象就都是可序列化的了。

接下来在FirstActivity 中的写法非常简单:

Person person = new Person();  
person.setName("Tom");  
person.setAge(20);  
Intent intent = new Intent(FirstActivity.this,       
SecondActivity.class);  
intent.putExtra("person_data", person);  
startActivity(intent); 

可以看到,这里我们创建了一个Person 的实例,然后就直接将它传入到putExtra()方法中了。由于Person 类实现了Serializable 接口,所以才可以这样写。

接下来在SecondActivity 中获取这个对象也很简单,写法如下:

Person person = (Person)   getIntent().getSerializableExtra("person_data"); 

方式二:Parcelable

除了Serializable 之外,使用Parcelable 也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent 所支持的数据类型,这样也就实现传递对象的功能了。
下面我们来看一下Parcelable 的实现方式,修改Person 中的代码,如下所示:

public class Person implements Parcelable {  
private String name;  
private int age;  
  
@Override  
public int describeContents() {  
    // TODO Auto-generated method stub  
    return 0;  
}  

@Override  
public void writeToParcel(Parcel dest, int flags) {  
    // TODO Auto-generated method stub  
    dest.writeString(name);  
    dest.writeInt(age);  
}  
public static final Parcelable.Creator CREATOR=new Parcelable.Creator() {  

    @Override  
    public Person createFromParcel(Parcel source) {  
        // TODO Auto-generated method stub  
        Person person=new Person();  
        person.name=source.readString();  
        person.age=source.readInt();  
        return person;  
    }  

    @Override  
    public Person[] newArray(int size) {  
        // TODO Auto-generated method stub  
        return new Person[size];  
    }  
   };   
 }  

Parcelable 的实现方式要稍微复杂一些。可以看到,首先我们让Person 类去实现了Parcelable 接口,这样就必须重写describeContents()和writeToParcel()这两个方法。其中describeContents()方法直接返回0 就可以了,而writeToParcel()方法中我们需要调用Parcel的writeXxx()方法将Person 类中的字段一一写出。注意字符串型数据就调用writeString()方法,整型数据就调用writeInt()方法,以此类推。

除此之外,我们还必须在Person 类中提供一个名为CREATOR 的常量,这里创建了Parcelable.Creator 接口的一个实现,并将泛型指定为Person。接着需要重写createFromParcel()和newArray()这两个方法,在createFromParcel()方法中我们要去读取刚才写出的name 和age字段,并创建一个Person 对象进行返回,其中name 和age 都是调用Parcel 的readXxx()方法读取到的,注意这里读取的顺序一定要和刚才写出的顺序完全相同。而newArray()方法中的实现就简单多了,只需要new 出一个Person 数组,并使用方法中传入的size 作为数组大小就可以了。

接下来在FirstActivity 中我们仍然可以使用相同的代码来传递Person 对象,只不过在SecondActivity 中获取对象的时候需要稍加改动,如下所示:

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

五、Intent传递Bitmap

bitmap默认实现Parcelable接口,直接传递即可

Bitmap bitmap = null;
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
intent.putExtra("bundle", bundle);

六、定义全局数据,传递数据

如果是传递简单的数据,有这样的需求,Activity1 -> Activity2 -> Activity3 -> Activity4, 你想在Activity中传递某个数据到Activity4中,怎么破,一个个页面传么?

显然不科学是吧,如果你想某个数据可以在任何地方都能获取到,你就可以考虑使用 Application全局对象了!

关键部分代码:

第一步自定义Application类:

class MyApp extends Application {
private String myState;
public String getState(){
    return myState;
}
public void setState(String s){
    myState = s;
  }
}

第二步AndroidManifest.xml中声明:

android:label="@string/app_name">

第三步在需要的地方调用:

class Blah extends Activity {
@Override
public void onCreate(Bundle b){
    ...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
    ...
  }
}

高逼格写法
:在任何位置都能获取到Application全局对象。

Applicaiton是系统的一个组件,他也有自己的一个生命周期,我们可以在onCraete里获得这个 Application对象。贴下修改后的代码吧!

class MyApp extends Application {
private String myState;
private static MyApp instance;

public static MyApp getInstance(){
    return instance;
}


public String getState(){
    return myState;
}
public void setState(String s){
    myState = s;
}

@Override
public void onCreate(){
    onCreate();
    instance = this;
    }
}

然后在任意地方我们就可以直接调用:MyApp.getInstance()来获得Application的全局对象!

七、单例模式传参

上面的Application就是基于单例的,单例模式的特点就是可以保证系统中一个类有且只有一个实例。 这样很容易就能实现,在A中设置参数,在B中直接访问了。这是几种方法中效率最高的。

①定义一个单例类:

public class XclSingleton  
{  
//单例模式实例  
private static XclSingleton instance = null;  
  
//synchronized 用于线程安全,防止多线程同时创建实例  
public synchronized static XclSingleton getInstance(){  
    if(instance == null){  
        instance = new XclSingleton();  
    }     
    return instance;  
}     
  
final HashMap mMap;  
private XclSingleton()  
{  
    mMap = new HashMap();  
}  
  
public void put(String key,Object value){  
    mMap.put(key,value);  
}  
  
public Object get(String key)  
{  
    return mMap.get(key);  
  }       
} 

②设置参数:

XclSingleton.getInstance().put("key1", "value1");  
XclSingleton.getInstance().put("key2", "value2");  

你可能感兴趣的:(Android Inten传递对象)