Android进程通讯——AIDL

本文参照《Android开发艺术探索》以及官方文档写的读书笔记,欢迎讨论,请勿转载。
在《Android开发艺术探索》这么书中使用跨进程通讯的两个场景:
1、通过多进程来获取多分内存空间
2、当前应用需要向其他应用获取数据

跨进程对我的理解就像请求网络调用接口似的,声明一个接口去在客户端调用,只不过调用的时候当前线程阻塞了,通过序列化的方式将用户自定义的对象(实现了Parcelable接口)或AIDL对象从客户端发送到服务端。然后服务端所对应的方法运行在一个Binder池内,将对象反序列化,从而得到对象,这时候将返回值返回,主线程从阻塞状态中重新恢复到运行的状态。

注意几点:
1、当非跨进程时(在Manifest没有指定process属性),当客户端调用AIDL方法时,客户端在UI线程,那么被调用的服务端的方法也在UI线程。反之。如果。客户端调用AIDL方法时,客户端在非UI线程,那么被调用的服务端方法也在非UI线程。
2、当跨进程时(在Manifest指定process属性),服务端的方法运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方式去实现。
3、当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,那么不能再UI线程中发起此远程请求。
4、如果一个远程方法是耗时的,我在客户端调用时会被挂起(我上面说的第3点)。但是如果我的远程方法返回void,也就是远程方法在怎么耗时,我客户端也不需要你返回数据,那么可以在AIDL方法中增加oneway关键字。
oneway void addBook(in Book book)
这样客户端就不会被挂起了。
5、在跨进程中,客户端传递的对象是经过序列化的,在服务端接收的对象,是经过反序列化的。服务端接收的对象只是里面的东西一样,但是根本不是同一个对象,这点要注意。
6、所有非原语(原语含义看下面)参数都需要指示数据走向的方向标记。可以是 in、out 或 inout。
原语默认为 in,不能是其他方向。
7、AIDL接口中只支持方法,不支持声明静态常量。

刚刚说到类似调用接口,所以得新建一个AIDL接口文件。

package ipc;
import ipc.Book;
import ipc.IOnNewBookArrivedListener;
// Declare any non-default types here with import statements

interface IBookManager {
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

            List<Book> getBookList();
            void addBook(in Book book);
            void registerListener(IOnNewBookArrivedListener listener);
}

在官网给的文档中说明AIDL文件支持的数据有:
Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
String
CharSequence
List
Map
在《Android开发艺术探索》中作者加入了其他内容
Parcelable:所有实现了Parcelable接口的对象
AIDL:所有的AIDL接口本身也可以在AIDL文件中使用

其中自定义的Parcelable对象和AIDL对象要显示import进来,不管他们是否和当前的AIDL文件位于同一包内。

最后还要声明一个实现Parcelable对象的 .aidl 文件。 此 .aidl 文件与 C 语言中的头文件类似,并未编译。

// Book.aidl
package ipc;
parcelable Book;
// IOnNewBookArrivedListener.aidl
package ipc;

// Declare any non-default types here with import statements
import ipc.Book;

interface IOnNewBookArrivedListener {
    void onNewBookArrivedListener(in Book newBook);
}
package ipc;

/**
 * Created by apple on 2018/1/1.
 */

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {
   
    public int bookId;
    public String bookName;

    public Book(String bookName, int bookId) {
        this.bookName = bookName;
        this.bookId = bookId;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookId=" + bookId +
                ", bookName='" + bookName + '\'' +
                '}';
    }

    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }

    public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    public int getBookId() {
        return bookId;
    }

    public void setBookId(int bookId) {
        
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的AIDLAndroid Interface Definition Language)是一种用于进程间通信的机制,它允许在不同进程中的组件之间进行通信。AIDL是一个基于接口的编程语言,它定义了一组方法,这些方法可以被其他进程中的组件调用。 AIDL的使用步骤如下: 1.定义AIDL接口:定义接口和方法,并在方法中指定参数和返回值类型。 2.实现AIDL接口:实现AIDL接口中定义的方法。 3.注册AIDL服务:在AndroidManifest.xml文件中注册服务。 4.使用AIDL服务:获取AIDL对象并调用方法。 下面是一个简单的例子,演示如何使用AIDL进行进程间通信。 1.定义AIDL接口 ``` interface IMyAidlInterface { void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); } ``` 2.实现AIDL接口 ``` public class MyAidlService extends Service { private static final String TAG = "MyAidlService"; private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Log.d(TAG, "basicTypes: " + anInt + ", " + aLong + ", " + aBoolean + ", " + aFloat + ", " + aDouble + ", " + aString); } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 3.注册AIDL服务 在AndroidManifest.xml文件中添加以下代码: ``` <service android:name=".MyAidlService" android:exported="true"> <intent-filter> <action android:name="com.example.MyAidlService" /> </intent-filter> </service> ``` 4.使用AIDL服务 ``` public class MainActivity extends AppCompatActivity { private IMyAidlInterface mService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(); intent.setAction("com.example.MyAidlService"); intent.setPackage("com.example"); bindService(intent, mConnection, BIND_AUTO_CREATE); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mService = IMyAidlInterface.Stub.asInterface(iBinder); try { mService.basicTypes(1, 2L, true, 3.0f, 4.0, "Hello, AIDL!"); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { mService = null; } }; } ``` 在上面的代码中,我们首先创建一个Intent对象,指定要绑定的服务的包名和类名。然后调用bindService()方法绑定服务,并在onServiceConnected()方法中获取AIDL对象,调用basicTypes()方法向服务传递参数。最后,在onServiceDisconnected()方法中释放AIDL对象。 以上就是使用AIDL进行进程间通信的基本步骤。需要注意的是,在使用AIDL时,必须确保服务已经启动,并且在AndroidManifest.xml文件中注册了服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值