2.2 Android中的IPC

一、Android中的IPC方式

  • 使用Bundle
  • 使用文件共享
  • 使用Messenger
  • 使用AIDL
  • 使用ContentProvider
  • 使用Socket

1.使用Bundle

Bundle实现了Parcelable接口,当我们在一个进程中启动了另一个进程的Activity、Service和BroadcastReceiver,可以在Bundle中附加我们需要传输的信息,通过Intent发送出去。、
传输的数据必须能被序列化,可以是 基本类型,实现了 Parcelable或Serializable接口的对象,或一些Android支持的特殊对象。、

2.使用文件共享

Android基于Linux,支持并发读/写文件,两个进程可以通过 读/写同一个文件来交换数据
MainActivity的onResume中序列化一个User对象到sd卡,SecondActivity的onResume中反序列化,恢复User对象。
Manifest中,MainActivity跑在包名进程中,SecondActivity跑在remote进程中

        <activity
                android:name=".MainActivity"
                android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
                android:name=".SecondActivity"
                android:label="@string/app_name"
                android:process=":remote">

User.java

public class User implements Serializable {
    private static final long serialVersionUID = 287483306032875107L;

    public int userId;
    public String userName;
    public boolean isMale;

    public User(int userId, String userName, boolean isMale){
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
    }

    @Override
    public String toString() {
        return "User{" +
               "userId=" + userId +
               ", userName='" + userName + '\'' +
               ", isMale=" + isMale +
               '}';
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       Button btnOpenSecondActivity = (Button) findViewById(R.id.btn_open_second_activity);
        btnOpenSecondActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        persistToFile();

    }

    public static final String FILE_NAME ="user.txt";
    private void persistToFile(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                User user = new User(1, "helloWorld", false);
                File dir = new File(Environment.getExternalStorageDirectory(),FILE_NAME);
                if(!dir.exists()){
                    try {
                        dir.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                ObjectOutputStream objectOutputStream = null;
                try {
                    objectOutputStream = new ObjectOutputStream(new FileOutputStream(dir));
                    objectOutputStream.writeObject(user);
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    if(null != objectOutputStream){
                        try {
                            objectOutputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }).start();
    }
}

SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

    }

    @Override
    protected void onResume() {
        super.onResume();
        recoverFromFile();
    }

    private void recoverFromFile(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                User user = null;
                File dir = new File(Environment.getExternalStorageDirectory() + "/" + MainActivity.FILE_NAME);
                if(dir.exists()){
                    ObjectInputStream objectInputStream = null;
                    try {
                        objectInputStream = new ObjectInputStream(new FileInputStream(dir));
                        user = (User) objectInputStream.readObject();
                        Log.d("SecondActivity", "### user = " + user);//### user = User{userId=1, userName='helloWorld', isMale=false}
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } finally {
                        if(null != objectInputStream){
                            try {
                                objectInputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }).start();
    }
}

序列化和反序列化 对象的内容是一样的,本质是2个对象
上边的例子,如果并发读/写,读出的内容可能不是最新的,并发写就更严重了,要尽量避免并发写或者使用线程同步来限制多个线程的写操作。

  • 多进程通信不要使用SharedPreferences
    SharedPreferences通过键值对的方式来存储数据,目录位于/data/data/包名/shared_prefs下,系统对SharedPreferences的读/写有一定的缓存策略,内存中会有一份SharedPreferences文件的缓存,多进程模式下,系统对它的读/写就会变得不可靠,当高并发读/写访问,就有很大几率会丢失数据。

3.使用Messenger

Messenger是一种轻量级的IPC方案,底层实现是AIDL,可以在不同进程中传递Message对象。
Messenger对AIDL做了封装,使进程间通信更简便;Messenger一次处理一个请求,服务端不存在并发执行的情形。

Messenger的使用步骤

  1. 在服务端创建一个Service 用于处理客户端请求,创建一个Handler 通过这个Handler创建一个Messenger对象;在onBind方法中返回Messenger的Binder
  2. 客户端进程中,首先绑定服务端的Service,onServiceConnected中用 服务端返回的IBinder创建一个Messenger,Message可以通过这个Messenger向服务端发送消息。
    如果服务端要回应客户端,客户端要创建一个Handler和一个新多Messenger,Message的replyTo参数将这个Messenger传递给服务端,服务端通过replyTo参数回应客户端。
        <service
            android:name=".messenger.MessengerService">
            <intent-filter>
                <action android:name="com.jieqiong.MessengerService.launch" />
            </intent-filter>
        </service>

        <activity android:name=".messenger.MessengerActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

服务端代码:MessengerService.java

public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    public static final int MSG_FROM_CLIENT = 1;
    public static final int MSG_FROM_SERVICE = 2;

    //MessengerHandler 用来处理客户端发送的消息
    private static class MessengerHandler extends Handler{

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MSG_FROM_CLIENT:
                    //收到客户端的消息
                    Log.i(TAG, "### handleMessage:: receive msg from Client: " + msg.getData().getString("msg"));

                    //给客户端发消息
                    Messenger client = msg.replyTo;

                    Message replyMessage = Message.obtain(null, MSG_FROM_SERVICE);
                    Bundle bundle = new Bundle();
                    bundle.putString("reply", "你的消息已经收到");
                    replyMessage.setData(bundle);

                    try {
                        client.send(replyMessage);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    //Messenger与Handler关联,Messenger的作用是将客户端发送的消息传递给MessengerHandler处理
    private final Messenger mMessenger = new Messenger(new MessengerHandler());

    @Override
    public IBinder onBind(Intent intent) {
        //onBind中返回Messenger的Binder对象
        return mMessenger.getBinder();

    }
}

客户端代码:MessengerActivity.java

public class MessengerActivity extends Activity {
    private static final String TAG = "MessengerActivity";

    private static class MessengerHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MessengerService.MSG_FROM_SERVICE:
                    //处理服务端返回的消息
                    Log.i(TAG, "### handleMessage:: receive msg from Service, " + msg.getData().getString("reply"));
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    private Messenger mMessenger;
    private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定成功后,根据服务端返回的 Binder 对象创建 Messenger
            Log.d(TAG, "### onServiceConnected::");

            mMessenger = new Messenger(service);
            Message msg = Message.obtain(null, MessengerService.MSG_FROM_CLIENT);

            Bundle bundle = new Bundle();
            bundle.putString("msg", "Hello,this is client");
            msg.setData(bundle);
            msg.replyTo = mGetReplyMessenger;//将Messenger通过replyTo 传递给服务端

            try {
                //Messenger向服务端发消息
                mMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }


        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);
        //绑定service
        Intent intent = new Intent(this, MessengerService.class);
        intent.setAction("com.jieqiong.MessengerService.launch");
        bindService(intent, mConnection, BIND_AUTO_CREATE);
    }
}
12-22 16:29:15.110 15143-15143/? D/MessengerActivity: ### onServiceConnected::
12-22 16:29:15.152 15143-15143/? I/MessengerService: ### handleMessage:: receive msg from Client: Hello,this is client
12-22 16:29:15.152 15143-15143/? I/MessengerActivity: ### handleMessage:: receive msg from Service, 你的消息已经收到

Messenger 和 Message都实现了 Parcelable 接口,通过Messenger来传输Message,Message中能使用的载体只有what、arg1、arg2、Bundle 以及 replyTo。Message的object字段,只有当对象实现了Parcelable 接口才能用object。
这里写图片描述

4.使用AIDL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值