Android中的IPC之使用Bundle

Android中的IPC方式

在Android中实现跨进程通信的方式有很多,具体的方式主要有以下几种:
1. 使用Bundle
2. 使用文件共享
3. 使用Messenger
4. 使用AIDL
5. 使用ContentProvider
6. 使用Socket

以下是各种IPC方式的优缺点和适用场景,图片源自《Android开发艺术探索》P121。

这里写图片描述


为什么可以使用Bundle实现IPC

我们知道,Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的操作,还可以在不同的组件之间传递数据。

  • 利用Intent传递数据主要分两种,基本类型数据和对象。
  • 但值得注意的是利用Intent来传递数据,它对要传递的数据类型是有要求的,我们传输的数据必须要能够被序列化。
  • 我们知道基本类型是能够被序列化的,那么对象呢?Android中主要有两种方式来实现对象序列化:Serilable接口和Parcelable接口。而Bundle为什么可以借助Intent来实现IPC呢?因为在Android中,有许多实现了Parcelable接口的类,如Bundle、Intent、Bitmap,同时List和Map也可序列化,前提是它们里面的每个元素才能序列化。这就解释了为什么我们可以利用Bundle来实现IPC了,同时也解释了为什么Intent本身也可以携带基本数据进行数据传递。下面用实际的例子来展示利用Intent作为载体传递基本数据,以及利用Intetn使用Bundle作为载体来实现进行间通信的具体实现。

使用Bundle和Intent传递数据

  1. 利用Intent本身作为载体传递基本类型数据

    • 实现思路:利用Intent中提供的一系统putExtra()方法的重载,把我们想要传递的数据暂存于Intent中,当要取数据的时候利用getXXXExtra()方法将数据从Intent中取出来。其中putExtra()方法接收两个参数,第一个参数键,用于后面从Intent中取值,第二个参数才是真正要传递的数据,getXXXExtra()方法根据要提取的数据的类型选择不用的方法,例如传递是的字符串,则用getStringExtra()方法,若是布尔类型,则用getBooleanExtra()方法,依次类推,注:除了String类型的getStrignExtra()是只传入一个键值参数外,其他基本类型的方法都是需要输入两个参数的,第一个是键值,第二个是默认数据值(当按键值找不到对应的数据时,就回返回这个默认的值)。
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        String data1 = "Hello";
        Double data2 = 98.0;
        intent.putExtra("data1_key",data1);
        intent.putExtra("data2_key",data2);
        startActivity(intent);
  • 说明:在FirstActivity中传递一个字符串“Hello”和一个双精度常数98.0。
    Intent在这里的作用有两个,其一是用于启动从FirstActivity活动到SecondActivity活动 其二是作为传递数据载体。
        Intent intent =  getIntent();
        String data1 = intent.getStringExtra("data1_key");
        Double data2 = intent.getDoubleExtra("data2_key",1);
  • 说明:在SecondActivity中先通过getIntent();方法获得启动SecondActivity活动的Intent的实例,然后利用getXXXExtra()方法来提取数据。

2. Intent结合Bundle作为载体进行数据传递

  • 实现思路:把需要传递的数据都保存在Bundle对象中,然后将Bundle对象存放在Intent里,提取数据时,先从Intent中取出Bundle,再从Bundle中逐一取出数据。
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        String data1 = "Hello";
        Double data2 = 98.0;
        Bundle bundle = new Bundle();
        bundle.putString("data1_key",data1);
        bundle.putDouble("data2_key",data2);
        intent.putExtras(bundle);
  • 说明:在FirstActivity中传递一个字符串“Hello”和一个双精度常数98.0,利用putXXX(key
    value)方法将数据在于一个Bundle对象中,然后把Bundle对象放在Intent中。
        Intent intent =  getIntent();
        Bundle bundle = intent.getExtras();
        String data1 = bundle.getString("data1_key");
        Double data2 = bundle.getDouble("data2_key")
  • 说明:在SecondActivity中,先通过getIntent()方法获取启动SecondActivity的Intent实例,接着利用getExtras()方法从Intent中取出Bundle,然后再从Bundle对象利用getXXX(key)方法取出数据。

3. 使用Bundle解决活动被回收会失去临时数据的问题
应用场景:应用中有一个活动A,用户在活动A的基础上启动了活动B,活动A就会进入停止状态,这时由于系统的内存不足,将活动A回收了,此时当用户从活动B中按Back键返回活动A的时候,由于活动A已被回收,此时会重新创建一次(即此时活动A并不会执行onRestart()方法,而是执行onCreate()方法),那么活动A中的临时数据和状态都会全没了。

解决办法:活动的onCreate()方法中有一个Bundle类型的参数,这个参数在一般情况下都是null的,但是如果在活动系统在回收之前有通过onSvaeInstanceState()方法的Bundle参数来保存数据的话,活动的onCreate()方法的Bundle参数就会带有之前所保存的全部数据,我们只需要再通过相应的取值方法将数据取出就可以了。

1). 在活动A中重写onSaveInstanceState()方法,利用该方法里面携带的Bundle参数,来存入存放临时的数据。

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String temData = "Something you want to save";
        outState.putString("data_key", temData);
    }

说明:利用putString(key,value)方法将一个字符串在于Bundle参数的outState中。

2). 在活动A的onCreate()方法中取出数据。

    protected void onCreate(Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null){
            String temData = savedInstanceState.getString("data_key");
        }
        ...

说明:利用getString(key)方法从Bundle参数的saveInstaceState中取出相应的数据。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章