(1)IPC是Inter-Process Communication的缩写,含义为进程间通讯或者跨进程通讯,是指两个进程之间进行数据交换的过程。java
(2)ANR是Application Not Responding的缩写,即应用无响应。主线程执行大量的耗时操做容易致使ANR现象发生。android
(3)在Android中最有特点的进程间通讯方式就是Binder了,经过Binder能够轻松地实现进程间通讯。git
(4)Android还支持Socket,经过Socket也能够实现任意两个终端或者两个进程之间的通讯。github
什么是进程,什么是线程,进程和线程是两个大相径庭的概念。数组
在操做系统中,线程是CPU调度的最小单元,同时线程是一种有限的系统资源。而进程指的一个执行单元,在PC和移动设备上指的是一个程序或者一个应用。一个进程能够包含多个线程,所以进程和线程是包含被包含的关系,最简单状况下,一个进程能够只有一个线程,即主线程,在Android里面也叫UI线程,在UI线程里才能操做界面元素。服务器
Android中通常都是经过Binder实现进程间通讯。除了Binder,Android还支持Socket,经过Socket也能够实现任意两个终端之间的通讯,固然一个设备上的两个进程之间经过Socket通讯天然也是能够的。网络
(1)多进程会带来不少意想不到的麻烦,由于Android为每个应用都分配了一个独立的虚拟机,或者说为每一个进程都分配了一个独立的虚拟机,不一样的虚拟机在内存分配上有不一样的地址空间,这就致使在不一样的虚拟机中访问同一个类的对象会产生多份副本。这样很就容易致使数据不一样步。并发
(2)全部运行在不一样进程的四大组件,只要它们之间须要经过内存在共享数据,都会共享失败。app
(3)主要有如下四方面的问题:ide
1)静态成员和单例模式彻底失效。(由独立虚拟机形成)
2)线程同步机制彻底失效。(同上)
3)SharedPreferences的可靠性降低。(存在并发读写的问题)
4)Application会屡次建立。(新的进程中又会致使进程所在的Application在新的虚拟机中再次建立)
(4)运行在同一个进程中的组件是属于同一个虚拟机和同一个Application的,同理运行在不一样进程的组件是属于两个不一样的虚拟机和Application的。
基于上面的这些问题,由于咱们须要学习进程间通讯机制!!!!!
当咱们须要经过Intent和Binder传输数据时就须要使用Parcelable或者Serializeble。Serializable和Parcelable接口能够完成对象的序列化过程。还有时候咱们须要把对象持久化到存储 设备上或者经过网络传输给其余客户端,这个时候也须要Serializable来完成对象的持久化。
Parcelable方法:
@Override public Test createFromParcel(Parcel in) { return new Test(in); }
从序列化后的对象中建立原始对象
@Override public Test[] newArray(int size) { return new Test[size]; }
建立指定长度的原始对象数组
protected Test/*Test为类名*/(Parcel in) { }
将序列化后的对象中建立原始对象
@Override public void writeToParcel(Parcel dest, int flags) { }
将当前对象 写入序列化结构中,其中flags标识有俩种值,0或者1,为1时标识当前对象须要做为返回值返回,不能当即释放资源,通常都会返回0
writeToParcel()的标记位为:
PARCELABLE_WRITE_RETURN_VALUE
@Override public int describeContents() { return 0; }
返回当前对象的内容描述,若是含有文件描述符,返回1,不然返回0,通常都返回0
describeContents()的标记位为:
CONTENTS_FILE_DESCRIPTOR
Serializable和Parcelable的区别:
Serializable是java中的序列化接口,使用简单,开销大,由于都是使用IO流进行操做
Parcelable是Android中的序列化方式,所以更适合用在Android平台上,缺点就是他使用起来比较麻烦,可是他的效率比较高,Parcelable主要运用在内存序列化上,经过Parcelable将对象序列化到存储设备中,或者将对象序列化后经过王阔传输也能够,可是过程比较复杂
Binder是Android中的一个类,它实现了IBinder接口,是跨进程通讯的一种方式
从Framework角度来讲,Binder是ServiceManager链接各类Manager和相应ManagerService的桥梁
从Android 应用层来讲,Binder是客户端和服务器端进行通讯的媒介,当bindService时,客户端能够获取服务器提供的服务或者数据,服务包括普通服务和基于ALDL的服务
AIDL有俩个类:Stub,Proxy
类中方法含义:
1)DESCRIPTOR:
Binder的惟一标识,通常用当前Binder的类名表示
2)asInterface()
用于将服务器端的Binder对象转换成客户端所需的AIDL接口类型的对象,转换是区分进程的,若是客户端和服务器端位于同一进程,那么此方法返回的就是服务器端的Stub对象自己,不然返回的是系统封装后的Stub.proxy对象
3)asBinder()
此方法返回当前Binder对象
4)onTransact()
此方法运行在服务器端中的Binder线程池,当客户端发起跨进程请求时,远程请求会经过系统底层封装后交由此方法来处理
服务器经过code能够肯定客户端所请求的目标方法是什么,接着从data中取出目标方法所需的参数,而后执行目标方法。当目标方法执行完毕后,就像reply中写入返回值
若是此方法返回false,那么客户端的请求会失败,所以咱们能够利用这个特性来作权限验证
Binder工做机制:
Binder中的方法:
linkToDeath和unlinkToDeath
Binder运行在服务端进程,若是服务端进程因为某种缘由异常终止,服务器端的Binder链接断裂,会致使远程调用失败,若是说你并不知道链接已经断裂,那么客户端的功能会收到影响,于是会有这俩个方法,当Binder死亡时,咱们额能够收到通知,从而从新发起链接请求而恢复链接。
使用这俩个方法
IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { //此处填写 } };
使用文件共享时要尽可能避免并发读写的状况,能够考虑使用线程同步来解决这种问题,因此文件共享的方式只适合在对数据同步要求不高的进程之浅见进行通讯。
简单实现 Messenger:
须要有服务端跟客户端
1.服务端进程:
建立一个Service来处理客户端的链接请求,同时建立一个Handler并经过它来建立一个Messenger对象,而后再Service的onBind中返回这个Messenger对象底层的Binder便可。
package com.example.messenger; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; public class MessengerService extends Service { private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch (msg.what){ case 100: Log.e("TAGS","客户端发送的消息:"+msg.getData().getString("key")); Messenger replyTo = msg.replyTo; Message message = Message.obtain(null,200); Bundle bundle = new Bundle(); bundle.putString("replyTo","服务器端已经收到了您发送的消息。"); message.setData(bundle); try { replyTo.send(message); } catch (RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage(msg); } } } private final Messenger messenger = new Messenger(new MessengerHandler()); @Override public IBinder onBind(Intent intent) { return messenger.getBinder(); } }
!!!须要注册service
<service android:name=".MessengerService" android:enabled="true" android:exported="true"></service>
2.客户端进程:
绑定服务端的Service,绑定成功后服务端返回的IBinder对象建立一个Messenger,经过这个 Messenger就能够向服务端发送消息,发送消息类型为Message对象。若是须要服务端可以回应客户端,就和服务端同样,咱们须要建立一个Handler并建立一个新的 Messenger,并把这个 Messenger对象经过Message的replyTo参数传递给服务端,服务端经过这个replyTo参数就能够回应客户端。
package com.example.messenger; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity { private Messenger mService; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mService = new Messenger(iBinder); Message message = Message.obtain(null, 100); Bundle bundle = new Bundle(); bundle.putString("key", "Hello Word!"); message.setData(bundle); //当客户端发送消息的时候,须要把接受服务器回复的Messenger经过Message的replyTo参数传递给服务器 message.replyTo = messenger; try { mService.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { unbindService(mConnection); super.onDestroy(); } private Messenger messenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case 200: getData(msg); break; default: super.handleMessage(msg); } } private void getData(Message msg) { Bundle data = msg.getData(); String replyTo = data.getString("replyTo"); Log.e("TAGS","服务器返回的消息:"+replyTo); } } }
Messenger的工做原理:
Messenger是以串行的方式处理客户端发来的消息,若是发送不少消息到服务端,可是服务端只能一个个去处理,因此遇到这种状况就不适合使用Messenger了,并且Messenger不支持跨进程调用服务端的方法。
Demo地址:
https://github.com/HaoMoster/Messenger
AIDL简介:
Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通讯,从而能够实现多个应用程序共享同一个Service的功能。
在多进程通讯中,存在两个进程角色(以最简单的为例):服务器端和客户端
服务器端(Service):
步骤一:新建定义AIDL文件,并声明该服务须要向客户端提供的接口
interface AIDL_Service1 { void AIDL_Service(); } //AIDL中支持如下的数据类型 //1. 基本数据类型 //2. String 和CharSequence //3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型; //4. AIDL自动生成的接口(须要导入-import) //5. 实现android.os.Parcelable 接口的类(须要导入-import)
步骤2:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)
public class MyService extends Service { // 实例化AIDL的Stub类(Binder的子类) AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() { //重写接口里定义的方法 @Override public void AIDL_Service() throws RemoteException { System.out.println("客户端经过AIDL与远程后台成功通讯"); } }; @Override public void onCreate() { super.onCreate(); System.out.println("执行了onCreat()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("执行了onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); System.out.println("执行了onDestory()"); } //在onBind()返回Stub类实例 @Nullable @Override public IBinder onBind(Intent intent) { System.out.println("执行了onBind()"); return mBinder; } @Override public boolean onUnbind(Intent intent) { System.out.println("执行了onUnbind()"); return super.onUnbind(intent); } }
步骤3:在AndroidMainfest.xml中注册服务 & 声明为远程服务
<service android:name=".MyService" android:process=":remote" android:exported="true"> </service>
客户端(Client):
步骤1:拷贝服务端的AIDL文件到目录下
步骤2:使用Stub.asInterface接口获取服务器的Binder,根据须要调用服务提供的接口方法
步骤3:经过Intent指定服务端的服务名称和所在包,绑定远程Service
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="scut.carson_ho.service_client.MainActivity"> <Button android:layout_centerInParent="true" android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="绑定服务" /> </RelativeLayout>
package scut.carson_ho.service_client; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import scut.carson_ho.service_server.AIDL_Service1; public class MainActivity extends AppCompatActivity { private Button bindService; //定义aidl接口变量 private AIDL_Service1 mAIDL_Service; //建立ServiceConnection的匿名类 private ServiceConnection connection = new ServiceConnection() { //重写onServiceConnected()方法和onServiceDisconnected()方法 //在Activity与Service创建关联和解除关联的时候调用 @Override public void onServiceDisconnected(ComponentName name) { } //在Activity与Service创建关联时调用 @Override public void onServiceConnected(ComponentName name, IBinder service) { //使用AIDLService1.Stub.asInterface()方法将传入的IBinder对象传换成了mAIDL_Service对象 mAIDL_Service = AIDL_Service1.Stub.asInterface(service); try { //经过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通讯 mAIDL_Service.AIDL_Service(); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService = (Button) findViewById(R.id.bind_service); //设置绑定服务的按钮 bindService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { System.out.println("点击了[绑定服务]按钮"); //经过Intent指定服务端的服务名称和所在包,与远程Service进行绑定 //参数与服务器端的action要一致,即"服务器包名.aidl接口文件名" Intent intent = new Intent("scut.carson_ho.service_server.AIDL_Service1"); //Android5.0后没法只经过隐式Intent绑定远程Service //须要经过setPackage()方法指定包名 intent.setPackage("scut.carson_ho.service_server"); //绑定服务,传入intent和ServiceConnection对象 bindService(intent, connection, Context.BIND_AUTO_CREATE); } }); } }
ContentProvider是Android中提供的专门用于不一样应用间进行数据共享的方式
Socket是网络通讯中的概念,他有TCP和UDP协议
TCP是面向链接的协议,提供稳定的双向通讯功能,他创建连接时须要进行三次握手 才能完成,为了提供稳定的数据传输功能,其自己提供了超市重传机制,所以具备很高的稳定性
UDP是无链接的,提供不稳定的单向通讯功能,也能够实现双向通讯功能,缺点是不保证数据必定可以正确传输,尤为是在网络拥塞的状况下