Android 教程 2020

前面我们大致了解了Activity 是一个应用组件,能为用户提供一个界面。以及如何新增activity。
一个App中,通常有多个界面。假设每一个界面对应一个activity,不同界面之间怎么跳转呢?

Intent

通常activity之间的跳转离不开Intent这个类。
Intent,直译为“意图”。我们把信息包裹在intent对象中,然后执行。
比如启动RelativeLayoutGuideAct这个activity。

1
startActivity(new Intent(getApplicationContext(), RelativeLayoutGuideAct.class));

这里用到一个很常见的方法startActivity (Intent intent)
startActivity属于Context类,Activity是Context的子类。

1
2
3
4
5
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity

现在我们知道了,启动activity需要使用Intent,调用startActivity方法。

带参数的跳转

在跳转去下一个页面时,我们可能会想携带一些信息到下一个界面去。例如携带一些文本,数字等等。
或者是一个对象。
这些信息我们可以交给Intent,传递到下一个activity去。下一个activity中拿到我们传入的Intent。

携带基本类型和String

我们直接看intent的方法。

1
2
3
4
5
Intent intent = new Intent(getApplicationContext(), SendParamsDemo.class);
intent.putExtra(SendParamsDemo.K_INT, 100);
intent.putExtra(SendParamsDemo.K_BOOL, true);
intent.putExtra(SendParamsDemo.K_STR, "Input string");
startActivity(intent);

intent的putExtra方法,可以传入参数。它接受1个String作为key,然后是具体参数。
例子中我们跳转去了SendParamsDemo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SendParamsDemo extends AbsActivity {

public static final String K_INT = "k_int";
public static final String K_BOOL = "k_bool";
public static final String K_STR = "k_str";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gotInput();
}

private void gotInput() {
Intent intent = getIntent();
if (intent != null) {
int i = intent.getIntExtra(K_INT, -1);
boolean b = intent.getBooleanExtra(K_BOOL, false);
String str = intent.getStringExtra(K_STR);
Log.d(TAG, "gotInput: i:" + i + ", b: " + b + ", str: " + str);
} else {
Log.d(TAG, "gotInput: input null.");
}
}
}
// log:
// com.rustfisher.tutorial2020 D/rustAppSendParamsDemo: gotInput: i:100, b: true, str: Input string

在这个activity中我们接收到了传入的参数。

观察intent的putExtra方法,我们发现它支持传入很多种参数。
int,byte, char, float, double, long, boolean,string,CharSequence或是它们的数组。
也可以传入Parcelable,Serializable对象或是对象数组。

传入Serializable对象

除了基本类型和String,可以传送对象吗?
答案是肯定的。Intent可以携带Serializable对象。
Serializable本身是一个接口,自定义的对象实现这个接口后,就可以被Intent携带。
比如我们改造一下DataTest类,让它实现Serializable接口。

1
public class DataTest implements Serializable { // 实现接口

然后将对象送给intent,再启动activity。

1
2
3
4
5
Intent intent = new Intent(getApplicationContext(), RecyclerViewDemo2Act.class);
DataTest out = new DataTest("input time", 233, 666, 999);
Log.d(TAG, "startInputData: sending object: " + out);
intent.putExtra(RecyclerViewDemo2Act.K_INPUT_DATA, out);
startActivity(intent);

被启动的activity接受传入的intent并取出对象。

1
2
3
4
5
Intent intent = getIntent();
if (intent != null) {
DataTest d = (DataTest) intent.getSerializableExtra(K_INPUT_DATA);
// 取出了对象,拿去显示
}

Serializable接口不含任何方法。实现了这个接口的类,系统会自动将其序列化。

我们打印出发送和接收到的对象。

1
2
startInputData: sending object: com.rustfisher.tutorial2020.recycler.data.DataTest@fb43df5
getInputData: input data object: com.rustfisher.tutorial2020.recycler.data.DataTest@a588b5c

可以发现这2个对象并不是同一个引用。但它们的“内容”是一样的。对象经历了序列化和反序列化的过程。

值得注意的是,Intent能携带的对象大小并不是无限制的。实际开发中,需要开发者自己预估传输的数据大小。

传入送Parcelable对象和传送Serializable对象类似,用同样的存入和取出操作。

工程放这里: https://github.com/AnRFDev/Tutorial2020