为什么要用AIDL

说到AIDL,每次就配套一个单词就是IPC,到底是怎么一回事,这事得从多进程说起。
有一天,我们写了一个类,类里面有一个静态变量。就像下面这样

public class UserBean { 

    public  static  int userCount=0;

}

原本的需求是这样的,通过这个User类的一个静态值,来全局共享一些用户信息,提供给A和B显示用,而这A和B是在两个独立的进程中(非线程)的,同时要求对这个数据有读写的能力。
关于如何开启多进程,估计很多程序是用不到的,因为他的场景不是很广泛,我们有可能是采用别的方案就避免掉了,例如广播之类的。
开启多进程的方法就是在我们的xml配置文件加多process属性,如下:

   

    

是不是很简单的感觉就可以开多进程了?

这里有一点需要注意的就是我们在名字前面的符号是什么,一个是“ : ”,另外一个是“.
两者导致的就是进程的名字不一样而已,同时如果以“:”开头,表示该进程为当前应用私有,和其他的组件是不会跑在同一个进程中的。后者是全局进程,可以和别的组件跑在同个进程,然后进行数据共享的。具体的内容以后再补充吧,说多有感觉跑远了。

现在假设我们先启动了A进程,然后设置值为1,接着启动B进程,打印数据,理论是等于1才对。

public class A{

    UserBean.userCount=1;
}

public class  B{


       Log.e(TAG, "count="+UserBean.userCount);
}

但我们居然发现打印是0, 这可坏了,这是为啥呢?
我们很当然的要怀疑起这个多进程到底怎么了?
简单的说就是,在安卓上,多进程就代表了”同时运行多个同样的app“
既然是两个同时运行的A和B,那两者想让就互补影响了。
不知有没映像,以前在诺基亚的塞班S60时代手机上有QQ共存版 ,同时运行多个QQ,每个QQ收到的数据是互不影响的,多进程大抵就是这种样子。
多进程带来的问题当然不知这些啦,我们的单例模式,线程同步等都显然形同虚设了,但需求还在那,我们需要把这事干了啊,那怎么办呢?
我们的不同进程要进行沟通解决啦,所以就有了这样那样的进程间进行通讯的机制(IPC)。

IPC有哪些?

能做进程间通讯的常见的有基于Binder的messenger,AIDL和Socket。据闻基于binder的效率最高,具体怎么比出来的,我也没看过。另外还有SharedPreferences,ContentProvider,Bundle等

AIDL

我们先写一个接口文件,用来给别的进程调用用的,这里我们提供一对get/set方法。

// UserManagerInterface.aidl
interface UserManagerInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

    int getUserCount();

    void setUserCount( in int n);

}

接着我们谷歌说的要求,写这么个独立的类,里面只有下面那个

// UserBean.aidl
package com.example.sanjay.myapplication.aidl;

parcelable UserBean;

最后我们再写一个简单的UserBean类

public class UserBean implements Parcelable {

    public  static  int UserCount=0;

    private  String userName;


    protected UserBean(Parcel in) {
        userName = in.readString();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public UserBean createFromParcel(Parcel in) {
            return new UserBean(in);
        }

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

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(userName);
    }
}

整个的结构就这样
为什么要用AIDL_第1张图片

然后为了我们的演示方便,我们在service里面加多一个类,如下,很简单,没什么特别要说的

public class AidlService extends Service {  

    private final UserManagerInterface.Stub mBidnerStub = new UserManagerInterface.Stub() {

        @Override
        public int getUserCount() throws RemoteException {
            return UserBean.UserCount;
        }

        @Override
        public void setUserCount(int n) throws RemoteException {
            UserBean.UserCount = n;
        }
    };

    public AidlService() {

    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBidnerStub;
    }
}

接着在我们的其中一个写下面的内容

public class MainActivity extends BaseActivity {

    private static final String TAG = MainActivity.class.getSimpleName();     

    UserManagerInterface mService;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.e(TAG, "connect service");
            mService = UserManagerInterface.Stub.asInterface(service);
            try {
                Log.e(TAG, "curUserCount=" + mService.getUserCount());
                mService.setUserCount(2);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            Log.e(TAG, "disconnect service");
            mService = null;
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        Intent intent = new Intent(this, AidlService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);        
    }

}

好了,核心的内容就这么点啦。基本都配置好了。
现在我们就可以做跨进程的通讯工作了。
由于时间限制,今天先写到这里,明天再补充

你可能感兴趣的:(android)