在我心中AIDL一直是个神秘的存在,它就像武侠世界中的上乘内功心法,让我这个只会点三脚猫功夫的人一直敬而远之!虽然说在平时开发中确实很少使用AIDL,但是它在面试中出现的频率还是相当高的,况且想要成为一名合格的Android开发人员,是无法避开AIDL的。最近又拿起了《Android开发艺术探索》这本书,看到了“IPC机制”这个章节,就借这个机会彻底揭开AIDL的神秘面纱,看看它究竟是何方神圣吧!
Android Interface Definition Language 直译:Android接口定义语言。
是 Android 提供的一种进程间通信 (IPC) 机制,通过这种机制,我们只需要写好aidl接口文件,编译时系统会帮我们生成Binder接口,此时我们就可以通过Binder去轻松实现进程之间传值或者调用方法啦。
我们都知道Android对单个应用是有内存限制的,当有需求需要突破这个限制的时候,我们需要另启进程扩大内存,而两个进程是完全独立的,此时AIDL是一种很有效的解决进程间通信的方式;再比如说,某些情况下远端的服务更适合运算或者更适合执行耗时操作,这时候我们会使用AIDL请求远程服务等等。
1、基本数据类型(int、long、char、boolean、double等);
2、String和CharSequence;
3、List 和 Map
4、所有实现了Parcelable接口的对象;
5、所有的AIDL接口
1、创建AIDL接口:
2、创建服务端:
3、创建客户端:
1、在AIDL中每个实现了Parcelable接口的类,都需要创建相应的AIDL文件(删除所有默认生产的代码,替换为以下两行代码)
package 包名;
parcelable 类名;
2、非基本类型的数据需要手动导入:
import 包名.类名
3、AIDL中,除了基本数据类型,其他类型的参数都必须标上方向
需要注意,不能一概使用inout,因为在底层实现是有开销的;
4、AIDL中只支持方法,不支持声明静态变量;
5、AIDL中实体类的包名必须与它所对应的aidl文件包名相同。
首先要声明一下,我这篇文章主要是《Android开发艺术探索》的读书总结,所以这里关于代码的部分,我是直接照着书上敲了一遍,主要是想了解编写AIDL的整个流程,其实真正自己敲的时候才会发现问题,然后才能更好更快的掌握。因为第一次写AIDL,个人理解能力也一般,光在流程上就遇到几个疑惑的地方,所以在这里我主要想说说编写流程。
1、创建一个工程,我们主要关注一下工程目录,如下图
2、接着在main目录下新建一个AIDL文件
文件名就叫IBookManager,看看默认生成的文件:
我们发现默认生成了一下代码:
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
此时,第一个疑惑出现了,这段代码是干什么的?必须存在吗?
看看注释,明白了,这是用来演示在AIDL中可以用作参数和返回值的一些基本类型。我们无需关心它,如果看着麻烦,完全可以把它全部删除,这样也显得代码干净!
3、在我们java目录下创建实体类Book,然后在aidl目录下创建Book所对应的aidl文件
这时候,第二个疑惑出现了,如下图:
如果先在java目录下创建了实体类Book,接着在aidl目录相同包下创建Book.aidl就无法创建了!难道对于AS来说它们是同一个包吗?具体原因还请留言。。。我的解决办法有两种:
4、将Book.aidl中的代码替换
这是默认生成的:
该删的就删,我们只需要简单的两行代码,替换后:
5、在第二步创建的IBookManager中添加以下代码:
// IBookManager.aidl
package com.example.kangbaibai.aidldemo;
// Declare any non-default types here with import statements
import com.example.kangbaibai.aidldemo.Book;
interface IBookManager {
List getBookList();
void addBook(in Book book);
}
6、这时候我们build一下工程,然后在Project模式下,打开app/build/generated/source/aidl,结构如下图:
看看系统为我们生成的IBookManager:
可以看到我们添加的两个方法已经存在了。到此AIDL代码全部写好了,该写服务端和客户端代码了。
7、服务端代码
新建一个服务BookManagerService:
package com.example.kangbaibai.aidldemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Created by kangbaibai on 2018/9/18.
*/
public class BookManagerService extends Service {
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList<>();
private Binder mBinder = new IBookManager.Stub() {
@Override
public List getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "Android"));
mBookList.add(new Book(1, "IOS"));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
别忘记在AndroidManifest.xml文件中注册,并且设置process,开启新进程:
服务端搞定!
8、客户端代码
在Activity中添加如下代码:
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List list = bookManager.getBookList();
for (Book book : list) {
Log.i(TAG, "before add query book list: " + book.toString());
}
Log.i(TAG, "------------------------------------------------------------");
Book newBook = new Book(3, "Android开发艺术探索");
bookManager.addBook(newBook);
List newList = bookManager.getBookList();
for (Book book : newList) {
Log.i(TAG, "after add query book list: " + book.toString());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
在onCreate中绑定:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_manager);
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
在onDestroy中解绑定:
@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
客户端也搞定了!允许一下,看看log:
09-19 14:51:28.770 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: before add query book list: com.example.kangbaibai.aidldemo.Book@db78307
09-19 14:51:28.770 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: before add query book list: com.example.kangbaibai.aidldemo.Book@f791c34
09-19 14:51:28.770 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: ------------------------------------------------------------
09-19 14:51:28.771 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: after add query book list: com.example.kangbaibai.aidldemo.Book@1610a5d
09-19 14:51:28.771 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: after add query book list: com.example.kangbaibai.aidldemo.Book@867efd2
09-19 14:51:28.771 28287-28287/com.example.kangbaibai.aidldemo I/BookManagerActivity: after add query book list: com.example.kangbaibai.aidldemo.Book@dbf48a3
到此一个简单的AIDL程序就搞定了,本文只是简单做个读书总结,并提出实际操作中遇到的疑惑和解决方法,之后我会继续深入了解AIDL原理等,希望大家支持~
代码已上传至github:https://github.com/kb18519142009/AidlDemo
欢迎star~