IPC通讯
IPC进程间通讯,对象需要被序列化。因为是通过二进制序列的形式来传递,内存中的对象需要通过序列化转成字节序列。
Serializable
Parcelable
都可以进行序列化。serializable序列过程中要进行大量io操作,耗内存,效率低。
parcelable,android专门用来做序列化的,内存消耗低,效率高。如果是进程间通讯,在内存中操作用parcelable。如果要保存到硬盘或网络传输用serializable,更稳定。
所有在IBunder中传输的接口,都要继承Iinterface接口。
跨进程通讯的方式
Bundle
写入intent中,基本数据类型,或者实现了serializable和parcelable接口的对象。intent最多不能超过500kb哦。
本地文件
通过本地共享的文件来实现通讯,高并发时,可能拿到的不是最新的数据,另外sp存储底层是xml,以键值对的形式存储的,应用中有对sp的内存缓存机制,当高并发时,可能造成数据丢失,所以不能用。
Messenger
客户端进程 绑定服务端的service,服务端返回一个IBinder对象,通过Messenger创建,Messenger.getBinder(),客户端绑定后返回一个IBinder对象,通过new Messenger(IBINDER) 创建出这个Messenger,就可以通过Message发送和接收数据了,回传信息是客户端创建一个Messenger对象,发送消息时通过message的replyTo参数,把这个Messenger传给服务端,服务端就可以回传数据。请看代码
public class MyServiceForMessenger extends Service {
@Override
public void onCreate() {
super.onCreate();
serviceList = new ArrayList<>();
Log.i("dongdong","创建了");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("dongdong","绑定了");
return stub.getBinder();
}
private List<Book> serviceList;
public class MyMessenger extends Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case Constant.MSG_FROM_CLIENT:
String msg1 = msg.getData().getString("msg");
Log.i("dongdong",msg1);
Messenger replyTo = msg.replyTo;
Message obtain = Message.obtain(null, Constant.MSG_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("delay","收到了,但是回复你好麻烦");
obtain.setData(bundle);
try {
replyTo.send(obtain);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
Messenger stub = new Messenger(new MyMessenger());
}
public class DemoBactivity extends Activity {
private Messenger messenger;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_a);
Button viewById = (Button) findViewById(R.id.btn_a);
Button viewById2 = (Button) findViewById(R.id.btn_getlist);
Button viewById3 = (Button) findViewById(R.id.btn_addlist);
Button viewById4 = (Button) findViewById(R.id.btn_startB);
viewById2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message obtain = Message.obtain(null, Constant.MSG_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg","这里是dongdongdemo发送的信息,服务端收到了吗");
obtain.setData(bundle);
obtain.replyTo = Bmessenger;
try{
messenger.send(obtain);
}catch(Exception t){
}
}
});
final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
messenger = new Messenger(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
viewById.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// startActivity(new Intent(DemoBactivity.this,DemoCactivity.class));
bindService(new Intent(DemoBactivity.this,MyServiceForMessenger.class),serviceConnection, Service.BIND_AUTO_CREATE);
}
});
}
private Messenger Bmessenger = new Messenger(new MyMessendClientHandler());
class MyMessendClientHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case Constant.MSG_FROM_CLIENT:
String delay = msg.getData().getString("delay");
Log.i("dongdong",delay);
break;
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onStart() {
super.onStart();
Log.i("dongdong","BBB启动了一次start");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i("dongdong","BBB启动了一次restart");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i("dongdong","BBB启动了一次onNewIntent");
}
@Override
protected void onResume() {
super.onResume();
Log.i("dongdong","BBB启动了一次onResume");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i("dongdong","BBB启动了一次onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i("dongdong","BBB启动了一次onRestoreInstanceState");
}
@Override
protected void onPause() {
super.onPause();
Log.i("dongdong","BBB启动了一次onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.i("dongdong","BBB启动了一次onStop");
}
}
message工作原理。
image.png
AIDL
这种是最常用的了。messenger为什么不常见,从实现方式可以看出,是串行。当高并发时,由handler处理。全部在handler的messagequeue中一件一件处理。如果有大量并发请求,就不行了。同时有时我们需要跨进程调用服务端的方法,Messenger页不行,但是AIDL行。
服务端
服务端需要创建一个service来监听客户端的请求。在服务端中写aidl,在aidl把暴露给客户端的接口声明,然后在service中实现这个接口。
客户端
绑定服务端的service,把返回的binder转成aidl接口所属的类型,然后通过这个接口就可以去调用了。
客户端调用服务端,服务端也可以回调客户端。
aidl具体实现 创建aidl接口,里面声明方法,如果入参有自定义的对象,要手动导入这个对象,并且对象要继承parcelable,并且在aidl文件夹中要声明出来。入参型参数前面加in 出参型out 综合性inout
package com.spu.dong.spu.activity.aidl;
// Declare any non-default types here with import statements
parcelable Book;
// IBookManager.aidl
package com.spu.dong.spu.activity.aidl;
import com.spu.dong.spu.activity.aidl.Book;
import com.spu.dong.spu.activity.aidl.AddBookListener;
// Declare any non-default types here with import statements
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
void registAddBookListener(in AddBookListener addBookListener);
void unRegistAddBookListener(in AddBookListener addBookListener);
}
package com.spu.dong.spu.activity.aidl;
import com.spu.dong.spu.activity.aidl.Book;
// Declare any non-default types here with import statements
interface AddBookListener {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void addOneBook(in Book book);
}
service中的实现,用到了RemoteCallBackList,这个不是list,底层是一个Map,把binde做key,把Callback<listener,cookies>做value,保存起来。有时的需求是服务端回调客户端,客户端有绑定和解绑回调接口的功能。客户端创建回调接口的实例a,传给服务端后,服务端会产生一个新的接口实例b,因为是不同线程的,不在同一个内存中。那么当客户端需要解绑时,把自己创建的回调接口a传过去时,服务端这是又产生了一个接口实例c,b和c不对应,所以没办法解绑。但是他们的底层binder是同一个,所以这个remotecallbacklist会遍历,根据listener.asbinder()的key,找到这个listener,然后去解绑。就可以了。并且remotecallbacklist会自动删除listener,在连接这个listener的客户端销毁时。遍历remotecallbacklist是要注意,调用.beginBroadcast时要配对使用.finishBroadcast(),哪怕你只是获取这个对象的内容多少。下面贴一下完整代码
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
serviceList = new CopyOnWriteArrayList<>();
addBookList = new RemoteCallbackList<>();
Log.i("dongdong","创建了");
}
private boolean serviceFlage = false;
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("dongdong","绑定了");
serviceFlage = true;
new Thread(new ServiceWork()).start();
return stub;
}
@Override
public boolean onUnbind(Intent intent) {
serviceFlage = false;
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
serviceFlage = false;
}
private CopyOnWriteArrayList<Book> serviceList;
private RemoteCallbackList<AddBookListener> addBookList;
IBookManager.Stub stub = new IBookManager.Stub(){
@Override
public List<Book> getBookList() throws RemoteException {
return serviceList;
}
@Override
public void addBook(Book book) throws RemoteException {
serviceList.add(book);
}
@Override
public void registAddBookListener(AddBookListener addBookListener) throws RemoteException {
//有人注册了这个服务,就在服务端保存一下这个listener 添加新书的时候。调用list中的所有addBookListener
addBookList.register(addBookListener);
}
@Override
public void unRegistAddBookListener(AddBookListener addBookListener) throws RemoteException {
addBookList.unregister(addBookListener);
}
};
private class ServiceWork implements Runnable{
@Override
public void run() {
try {
//绑定了
while (serviceFlage) {
Thread.sleep(5*1000);
Book book = new Book(serviceList.size() + 1, "book#bookid" + (serviceList.size() + 1));
//加本书
serviceList.add(book);
//监听的方法 都调用一下
int N = addBookList.beginBroadcast();
for (int i = 0;i<N;i++ ){
AddBookListener broadcastItem = addBookList.getBroadcastItem(i);
broadcastItem.addOneBook(book);
}
addBookList.finishBroadcast();//finishBroadCast 和 beginBroadcase 配对使用
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class DemoAactivity extends Activity {
private IBookManager iBookManager;
AddBookListener.Stub stub;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_a);
Button viewById = (Button) findViewById(R.id.btn_a);
Button viewById2 = (Button) findViewById(R.id.btn_getlist);
Button viewById3 = (Button) findViewById(R.id.btn_addlist);
Button viewById4 = (Button) findViewById(R.id.btn_startB);
stub = new AddBookListener.Stub() {
@Override
public void addOneBook(Book book) throws RemoteException {
//应该发送给子线程去处理。这里简单点。
Log.i("dongdong","我看下是什么书"+book.bookId+book.bookName);
}
};
viewById4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//startActivity(new Intent(DemoAactivity.this,DemoBactivity.class));
//解除绑定
try {
iBookManager.unRegistAddBookListener(stub);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
viewById2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try{
List<Book> bookList = iBookManager.getBookList();
Log.i("dongodng",bookList.size()+"");
}catch(Exception t ){
Log.i("dongdong","ipc失败");
}
}
});
viewById3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try{
iBookManager.addBook(new Book(11,"好书"));
}catch(Exception t ){
Log.i("dongdong","ipc失败");
}
}
});
final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iBookManager = IBookManager.Stub.asInterface(iBinder);
try {
iBookManager.registAddBookListener(stub);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
viewById.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//startActivity(new Intent(DemoAactivity.this,DemoBactivity.class));
//进程间通信
Intent intent = new Intent(DemoAactivity.this,MyService.class);
boolean b = bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
//绑定服务后。注册一下监听
}
});
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i("dongdong","AAA启动了一次saveinstance");
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
实际上,根据binder机制我们知道。服务端调用客户端的回调方法时,这个方法是运行在客户端的binder线程池中执行的,为了ui操作,我们需要一个handler把他切换到主线程中去操作。我对这句话的理解,因为客户端发起远程请求时,线程会挂起,直至服务端返回数据,所以是耗时的,所以尽量创建一个子线程去发起远程请求,那么回调也是在子线程中,如果要回到主线程操作ui,就需要一个handler。另外binder中的方法运行在服务端的线程池中,所以binder的方法都应采用同步的方式去实现。
过程中如果binder断裂,binder死亡了怎么办,通过linktoDeath()设置死亡代理,binder死亡时,会回调代理中的方法,我们可以从新创建连接。
首先创建deathRecipient, 这是个接口,里面有一个binderdied,当binder死亡,系统会回调binderdied,我们在方法里移出之前绑定的binder代理,重新绑定。
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mBookManager == null)
return;
mBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
mBookManager = null;
// TODO: 重新绑定远程service
}
};
service死亡。binder断裂 怎么办?
1.给binder设置死亡代理,deathRecipient。
mService = IMessageBoxManager.Stub.asInterface(binder);
binder.linkToDeath(mDeathRecipient, 0);
2.断裂会回调onServiceDisConnector的方法,方法中做处理。
3.安全性,我们的service不是谁想调谁就调的,那么我们在onBind 或者onTransact中做判断,一个是自定义权限,一个是或者client的pid uid 来做一些判断。
ContentProvider
1.以表格的形式来组织数据,可以包含多张表,对于每张表格来说,有行和列的层次性,和数据库类似。底层数据看起来很像一个sqlite数据库,但是contentprovider对底层数据存储方式没有任何要求,可以是数据库,可以是文件,甚至一个内存中的对象进行数据存储。
2.例子。继承contentpervider,实现其中方法,使用UriMatcher,addUri将uri和uricode关联起来,我们就可以根据uri拿到code,match(uri)就知道外界对哪个表进行操作,可对不同的表进行操作,authorities是contentprovider的唯一标识,很重要。实现SqliteOpenHelper,在onCreate方法中创建XXX.db。getContentResolver来操作数据库,ContentResolver代理的是ContentProvider。增删改查都运行在binder的线程池中,ContentResolver可以注册观察者registerContentObserver。
Socket
分为流式套接字和数据报套接字两种,对应网络的传输控制层的两种协议,TCP协议和UDP协议。
TCP和UDP的区别:
1.TCP是面向连接的,UDP是不需要连接的。
2.TCP可以提供的稳定的双向通信,UDP不稳定的单向通信(可以做双向,但还是不稳定)。
3.TCP需要三次握手建立连接,并具有超时重传机制,稳定性高,占用资源多,UDP不需要建立连接,稳定性低,占用资源少。从性能上看,UDP效率高。UDP没有阻塞控制。
TCP三次握手
ACK 应答的,SYN同步的。
1.A向B发送数据包,SYN = 1,seq number随机(A知道)。状态:CLOSE>>SYN_SENT。
2.B接收到数据包,SYN= 1 标识A要建立连接,B向A发送数据包,SYN = 1,ACK = 1,ack = seq+1,seq number。状态CLOSE>>LISTEN>>>>SYN_RECV。
3.A接到数据包,SYN = 1 B可以建立连接,ack判断是自己发出去的数据包得到的返回,A向B发送数据包,ACK = 1,ack = B的seq +1,seq = A的seq+1。状态:SYN_SENT>>ESTABLISHED。
4.B拿到数据包,SYN = 1 ,ack 正确。SYN_SENT>>>ESTABLISHED。
TCP四次挥手
任何一方都可以发起关闭。
1.A向B发送,FIN = 1,seq = n。状态 ESTABLISHED>>FIN_WAIT_1。
2.B接到数据包,FIN = 1,哦是要关闭。可我还没传输完。B发送数据包。ACK = 1,ack = n=1,seq = v。状态:ESTABLISHED>>>CLOSE_WAIT。
3.B我传输完了,B发送数据包,FIN = 1,ACK = 1,ack = n+1,seq = m。B:CLOSE_WAIT>>>LASK_TASK。
4.A接到数据包,FIN =1,ack对的,哦可以关了,A发送数据包,ACK = 1,seq = n+1,ack = m+1。状态:接到包A:FIN_WAIT_1>>>FIN_WAIT_2。发送包A:FIN_WAIT_2>>>TIME_WAIT。2sml后关闭TIME_WAIT>>>CLOSE。
5.B接到数据包,ack 对的,seq对的。LAST_TASK>>CLOSE。
为什么三次握手?
信道不稳定,数据要稳定,三次最少,为什么不是两次,A要确认一次,防止网络延迟,使B一厢情愿建立连接而A不知道。
为什么四次挥手?
第一次客户端要断开连接,服务端并不一定已经发送完数据,不能同步。所以要发送客户端两次,一次我知道了,一次我发完了。
Binder连接池 一个servicer 管理多个AIDL
创建对象
// aa.aidl
package com.xdw.myapplication.demo;
// Declare any non-default types here with import statements
parcelable Book;
创建两个aidl
// BookDelete.aidl
package com.xdw.myapplication.demo;
import com.xdw.myapplication.demo.Book;
// Declare any non-default types here with import statements
interface BookDelete {
int deleteBook(in Book book);
}
// BookMagager.aidl
package com.xdw.myapplication.demo;
import com.xdw.myapplication.demo.Book;
// Declare any non-default types here with import statements
interface BookMagager {
String addBook(in Book book);
}
创建aidl管理
// QueryManager.aidl
package com.xdw.myapplication.demo;
// Declare any non-default types here with import statements
interface QueryManager {
IBinder getBinder(in int code);
}
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable{
public int code;
public String name;
public Book(int code,String name){
this.code = code;
this.name = name;
}
protected Book(Parcel in) {
code = in.readInt();
name = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(code);
dest.writeString(name);
}
}
image.png
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_connect:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.xdw.myapplication","com.xdw.myapplication.service.ServiceDemo"));
bindService(intent,new myConnection(), Service.BIND_AUTO_CREATE);
break;
case R.id.btn_delete:
try {
IBinder binder = queryManager.getBinder(0);
BookDelete bookDelete = BookDelete.Stub.asInterface(binder);
int num = bookDelete.deleteBook(new Book(0, "删除的书"));
Toast.makeText(ClientActivity.this,num+"",Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_add:
try{
IBinder binder = queryManager.getBinder(1);
BookMagager bookMagager = BookMagager.Stub.asInterface(binder);
String bookName = bookMagager.addBook(new Book(11111, "添加的书"));
Toast.makeText(ClientActivity.this,bookName,Toast.LENGTH_SHORT).show();
}catch(Exception t){
}
break;
}
}
service
image.png