IPC进程间通讯,自我学习总结
明确:安卓中开启多线程只有一种方法,就是制定android:process,除此之外没有其他办法,也就是说我们无法给一个线程或者一个实体类制定其运行时所在的进程。
明确:“:”和“.”的区别,用
“:”开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中,而进程名不以
“:”开头的属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中。
其次:我们要知道安卓为每一个进程分配了一个独立的虚拟机,这就导致了不同的虚拟机中访问同一个类的对象会产生多份副本。
所以,所有运行在不同进程中的四大组件,只要它们之间需要通过内存来共享数据,都会失败,这也是多进程锁带来的主要影响。
正常情况下,四大组件中间不可能不通过一些中间层来共享数据,那么通过简单的指定进程名来开启多进程都会无法正确运行。当然,特殊情况下,某些组件之间不需要共享数据,这个时候可以直接指定
android:process属性来开启多进程,但是这个情况是不常见的,几乎所有情况都需要共享数据。
一般来说,使用多进程会造成如下几方面的问题:
1.静态成员和单列模式完全失效
2.线程同步机制完全失效
3.Sharepreferences的可靠性下降。
4.Application会多次创建。
我们也可以这么理解同一个应用间的多线程:它就相当于两个不同的应用采用了ShareUID的模式,这样能够更加直接地理解多进程模式的本质。
多进程会带来很多问题,但是我们却不能因此不重视它。为了解决这些问题,系统提供了很多跨进程通信方法,虽然说不能直接地共享内存,但是通过跨进程通信我们还是可以实现数据交换。
序列化
private void Indata() { try { File extDir = getExternalStorageDirectory(); String filename = "cache.txt"; File fullFilename = new File(extDir, filename); User user = new User(0,"an",true); ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(fullFilename)); o.writeObject(user); o.close(); } catch (IOException e) { e.printStackTrace(); Log.d("Tag","错误信息"+e); Toast.makeText(TwoActivity.this,"IO错误",Toast.LENGTH_SHORT).show(); } }
反序列化
private void Indata() { try { File extDir = getExternalStorageDirectory(); String filename = "cache.txt"; File fullFilename = new File(extDir, filename); ObjectInputStream in = new ObjectInputStream(new FileInputStream(fullFilename)); User o = (User)in.readObject(); Log.d("Tag",""+ o.getUserid());//0 Log.d("Tag",""+o.getUsername());//an Log.d("Tag",""+ o.ismale());//true in.close(); tv_1.setText("id"+ o.getUserid()+"名字"+o.getUsername()+"正确与否"+ o.ismale()); } catch (IOException e) { e.printStackTrace(); tv_1.setText("IO错误"); } catch (ClassNotFoundException e) { e.printStackTrace(); tv_1.setText("其他错误"); } }
效率上Parcelable比Serializable效率高很多,
Serializable用来实现对象的持久化.
binder原理,太复杂,理过一次后记不住了:记住一句话AIDL文件的本质是系统为我们提供了一种实现BInder的工具,仅此而已。
IPC的方式:
1.使用Bundle.实现了parcellable接口
1.使用Bundle.实现了parcellable接口
2.文件共享
3.使用Messenger底层是AIDL,binder
public class MessengerActivity extends Activity { private static final String Tag = "MessengerActivity"; private Messenger messenger; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { messenger = new Messenger(service); Message msg = Message.obtain(null,33); Bundle data = new Bundle(); data.putString("msg","啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"); msg.setData(data); msg.replyTo = messengers; try { messenger.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.service); Intent intent = new Intent(MessengerActivity.this,MessengerService.class); bindService(intent,connection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { unbindService(connection); super.onDestroy(); } private Messenger messengers = new Messenger(new MessengerHandlers()); private static class MessengerHandlers extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what){ case 22: Log.d("Tag","服务端端发过来的消息"+msg.getData().getString("reply")); default: super.handleMessage(msg); } } } }
public class MessengerService extends Service{ private static final String TAG = "MessengerService"; private static class MessengerHandlers extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what){ case 33: Log.d("Tag","客户端发过来的消息"+msg.getData()); Messenger client = msg.replyTo; Message message = Message.obtain(null,22); Bundle bundle = new Bundle(); bundle.putString("reply","服务端回复"); message.setData(bundle); try { client.send(message); } catch (RemoteException e) { e.printStackTrace(); } default: Log.d("Tag","客户端发过来失败"+msg.getData()); super.handleMessage(msg); } } } private final Messenger messenger = new Messenger(new MessengerHandlers()); @Nullable @Override public IBinder onBind(Intent intent) { return messenger.getBinder(); } }
4.aidl(如果有大量并发请求Messenger就不合适了)
可以使用权限验证来保护服务端(保证客户端)
5.使用Contentprovider内容提供者,底层是binder
6.Socket套接字
TCP稳定,三次握手,双向
UDP不稳定,单向,性能好,挺不错的