从Intent的定义可知,Intent除了定位目标组件外,另外一个职责就是传递数据信息。
1、传递基本数据
Intent间传递数据一般有两种方法:一种是通过data属性,另一种是通过extra属性。
data属性是一种URL,它可以是指向我们熟悉的HTTP,FTP网络地址,也可以指向ContentProvider提供的资源,通过调用Intent的setData方法可以放入数据,相应地,调用getData方法可以取出数据。
例如:需要启动Android内置的浏览器:
Intent intent = new Intent();
intent,setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(http://www.google.com.hk));
startActivity(intent);
startActivity(intent);
由于data属性只能传递数据的URL地址,如果需要传递一些数据对象,则就需要利用extra了。
extra可以通过Intent的putExtra方法放入数据,方法putExtra的参数是一个Bundle对象,(所谓Bundle是专门用来在Android的应用组件之间传递数据的一种对象,它本质上是一个Map对象,可以将各种基本的数据类型的数据保存在Bundle类中进行打包传输)
例子:
调用ActicityOne的代码片段:
firstbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// 显式启动 Activity One
Intent i = new Intent(getApplicationContext(),
ActivityOne.class);
Bundle bd = new Bundle(); bd.putString("username", "android");
i.putExtra("attachment", bd);
startActivity(i);
}
});
Acticity的代码:
package com.demo.intent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class ActivityOne extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityone);
String tag = "ActivityOne onCreate..";
Intent i = getIntent();
Bundle b = i.getBundleExtra("attachment");
Log.d(tag, b.getString("username"));
Log.d(tag, "han been started ");
}
}
从Intent获取信息的代码放在onCreate方法中,在通常情况下没有问题,但是存在隐患。
首先在默认情况下,当通过Intent获取一个Activity的时候,就算已经存在一个相同的正在运行的Activity,系统都会创建一个新的Activity实例并显示出来,为了不让Activity多次实例化,开发人员需要在AndroidManiFest.xml配置Activity的加载方式(launchMode)一实现单任务模式:
<activity android:name="Activity"
android:launchmode="singleTask">
</activity>
launchMode为singleTask时候,通过Intent启动一个Activity,如果系统已经存在一个实例,系统就会将请求发送到这个实例上去,但这时,系统就不会再调用通常处理请求数据的onCrtate()方法,而是调用onNewIntent()方法。
最安全的方法便是在onCrtate和onNewInten方法中调用同一个处理数据的方法:
package com.demo.intent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class ActivityOne extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
processExtraData();
}
protected void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
processExtraData();
}
private void processExtraData(){
Intent intent = getIntent();
//在下面处理Intent附加数据
}
}
2、复杂对象的传递
传递的复杂的自定义对象,利用Intent传递有两种方法:
一种是Bundle.putSerializable(Key,Object),另一种是BUundle.putParcelableArrayListExera(Key,Object),
Object的条件:一种是实现Serializable接口,而后者实现了Parcelable接口,在Android运行环境中推荐使用Parcelable接口,它不但可以利用Intent传递,还可以在远程方法调用使用。
实现Parcelable需要以下操作:
writeToParcel方法:该方法将类的数据写入外部提供的parcel中。
describeContents方法:返回内容描述信息的资源ID。
静态的Parcelable.Creator接口,本接口有两个方法:
createrFromParcel(Parcel in ):实现从parcel实例中创建出类的实例的功能。
new Array(int size) :创建一个类型T,长度为size的数组。
演示:
实体类: student.java
package com.demo.intent;
import java.util.HashMap;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
public Student() {
name = "unknown";
scores = null;
}
public HashMap<String, String> scores = new HashMap<String, String>();
public String name;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeMap(scores);
dest.writeString(name);
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
@Override
public Student createFromParcel(Parcel source) {
Student p = new Student();
p.scores = source.readHashMap(HashMap.class.getClassLoader());
p.name = source.readString();
return p;
}
@Override
public Student[] newArray(int size) {
// TODO Auto-generated method stub
return new Student[size];
}
};
}
作为封装学生信息的实体类,它实现了Parcleable接口。
main.java
package com.demo.intent;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button firstbtn = (Button) findViewById(R.id.activity1);
firstbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// 显式启动 Activity One
Intent i = new Intent(getApplicationContext(),
ActivityOne.class);
Bundle bd = new Bundle();
Student s = new Student();
HashMap<String, String> sc = new HashMap<String, String>();
sc.put("english", "98");
sc.put("computer", "75");
s.name = "tom";
s.scores = sc;
ArrayList<Student> al = new ArrayList<Student>();
al.add(s);
i.putParcelableArrayListExtra("attachment2", al);
bd.putString("username", "android");
i.putExtra("attachment", bd);
startActivity(i);
}
});
}
}
说明:首先创建一个student,然后将其放入ArrayList中,并调用putParceableArrayListExtra()方法将其加入Intent
activityone.java
package com.demo.intent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class ActivityOne extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityone);
String tag = "ActivityOne onCreate..";
Intent i = getIntent();
Bundle b = i.getBundleExtra("attachment");
Log.d(tag, b.getString("username"));
Log.d(tag, "han been started ");
ArrayList<Student> al = new ArrayList<Student>();
al = i.getParcelableArrayListExtra("attachment2");
if (al != null) {
Student s = (Student) al.get(0);
Log.i(tag, "---->" + s.name);
Iterator iter = s.scores.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
String val = (String) entry.getValue();
Log.i(tag, key.toString() + val.toString());
}
}
}
}
说明:为获取传递过来的实现Parcleable接口的对象,首先调用getParcelableArrayListExtra方法获得一个ArrayList对象,然后从ArrayList中操作student对象即可。
package com.demo.intent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class ActivityOne extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityone);
String tag = "ActivityOne onCreate..";
Intent i = getIntent();
Bundle b = i.getBundleExtra("attachment");
Log.d(tag, b.getString("username"));
Log.d(tag, "han been started ");
ArrayList<Student> al = new ArrayList<Student>();
al = i.getParcelableArrayListExtra("attachment2");
if (al != null) {
Student s = (Student) al.get(0);
Log.i(tag, "---->" + s.name);
Iterator iter = s.scores.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
String val = (String) entry.getValue();
Log.i(tag, key.toString() + val.toString());
}
}
}
}