AIDL终极篇之AIDL架构设计

移动开发 waitig 425℃ 百度已收录 0评论

本技术博文计划分为三个系列:
一、AIDL的基础,http://blog.csdn.net/wangqiubo2010/article/details/78601666。
二、AIDL之Messenger,http://blog.csdn.net/wangqiubo2010/article/details/78615047.。
三、AIDL终极篇之AIDL架构设计。


本文为AIDL设计的终极篇,AIDL架构设计。

在设计这个架构设计之前,思考一个问题:随着项目越来越大,如果请求的服务器中的服务类型越来越多,按照普通的设计有两种办法。
第一,服务器所执行的方法全部放在一个或者少量几个类中,这里有个问题就是,多种不同类型的请求全部塞在一个类中,并且类越来越庞大,这和职责分离完全背离。

第二,建立无数个service,每个service实现一种类型服务,也即是每种类型都生成一个IBinder,并且会有无数个链接,这样的设计服务器迟早会被拖垮。


针对以上问题,现在就是对AIDL的设计架构进行改进。

AIDL新设计架构图如下:
这里写图片描述

对本架构进行解析:

服务端架构解析:
1、IBinder1、IBinder2、IBinder3…,这些都是根据各种功能类型实现的每个Stub。

2、AIDLPoolService(IBinder管理器)。
AIDLPoolService其实就是客户端需要连接的服务,但是本服务提供给客户端的IBinder其实是一个IBinder管理器,本管理器只有一个方法queryBinder,这个方法就是根据ID来分发查询所需要类型的IBinder,入上面的IBinder1、IBinder2等。

服务器这样的设计就能解决以上2个问题。
第一,IBinder1、IBinder2、IBinder3…,无论你有多少种类型的功能,都可以无限增加,既解决了职责分离问题,又实现了动态增加功能。
第二,本架构连接服务器只会请求一次,请求成功之后,后续只要传一个IBinder的ID就可以查询到所需求的IBinder,则客户端获取到之后就可以直接调用服务器的方法。

客户端架构解析:
1、client1、client2、client3……,就是客户端每个功能模块了。
2、AIDLPoolClient,封装了对Service的连接,有一个IBinder查询器,client1、client2、client3……只要传个ID过去就可以直接获取到所需求的IBinder。


以上架构代码如下:

//AIDLPoolService(IBinder管理器)。
package com.example.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

/**
 * Created by wangqiubo on 2017/5/17.
 */

public class AidlPoolService extends Service{
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return aidlPool;
    }

    private static IBinder aidlPool = new AidlPoolImpl();
}
//AidlPoolImpl.java
package com.example.myservice;

import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;

import com.example.wangqiubo.myaidl.IAidlPool;

/**
 * Created by wangqiubo on 2017/5/17.
 */

public class AidlPoolImpl extends IAidlPool.Stub {
    public static final int BOOK_BINDER_ID = 0;
    public static final int USER_BINDER_ID = 1;
    IBinder mBinder = null;
    @Override
    public IBinder queryBinder(int binderId) throws RemoteException {
//        Debug.waitForDebugger();
        switch(binderId){
            case BOOK_BINDER_ID:
                mBinder = new BookImpl();
                break;
            case USER_BINDER_ID:
                mBinder = new UserImpl();
                break;
        }
        return mBinder;
    }
}

//BookImpl.java(AIDL的实现)
package com.example.myservice;

import android.os.RemoteException;

import com.example.wangqiubo.myaidl.Book;
import com.example.wangqiubo.myaidl.IBookCallBackInterface;
import com.example.wangqiubo.myaidl.IBooksAidlInterface;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by wangqiubo on 2017/5/17.
 */

public class BookImpl extends IBooksAidlInterface.Stub {
    List<Book> books = new ArrayList<>();
    @Override
    public List<Book> getBookList() throws RemoteException {
        return books;
    }

    @Override
    public void addBook(Book book) throws RemoteException {
        books.add(book);
    }

    @Override
    public void registerBookEvent(IBookCallBackInterface bookEvent) throws RemoteException {

    }

    @Override
    public void unregisterBookEvent(IBookCallBackInterface bookEvent) throws RemoteException {

    }
}
//UserImpl.java,AIDL的实现。
package com.example.myservice;

import android.os.RemoteException;

import com.example.wangqiubo.myaidl.IUserAidlInterface;
import com.example.wangqiubo.myaidl.User;

import java.util.ArrayList;
import java.util.List;


public class UserImpl extends IUserAidlInterface.Stub {
    List<User> userList = new ArrayList<>();
    @Override
    public void addUser(User user) throws RemoteException {
        userList.add(user);
    }

    @Override
    public List<User> getUsers() throws RemoteException {
        return userList;
    }
}

以下是客户端代码。

package com.example.wangqiubo.myapplication;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.example.wangqiubo.myaidl.IAidlPool;

/**
 * Created by wangqiubo on 2017/5/17.
 */

public class AidlPool {
    public static final int BOOK_BINDER_ID = 0;
    public static final int USER_BINDER_ID = 1;
    private IAidlPool aidlPoolInterface = null;
    private IBinder mBinder = null;

    public AidlPool(Context context){
        Intent intent = new Intent();
        ComponentName componentName = new ComponentName("com.example.myservice","com.example.myservice.AidlPoolService");
        intent.setComponent(componentName);
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    public IBinder queryBinder(int binderId) throws RemoteException {
//        switch(binderId){
//            case BOOK_BINDER_ID:
//                mBinder = aidlPoolInterface.queryBinder(binderId)
//                break;
//            case USER_BINDER_ID:
//
//                break;
//        }
        //Debug.waitForDebugger();
        Log.d("aidlPool:", " queryBinder");
        if (null == aidlPoolInterface)
            return null;
        mBinder = aidlPoolInterface.queryBinder(binderId);
        return mBinder;
    }

    public IAidlPool getAidlPoolInterface(){
        return aidlPoolInterface;
    }


    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("aidlPool", " ServiceConnection");
            aidlPoolInterface = IAidlPool.Stub.asInterface(service);
            if (null != aidlPoolInterface)
                Log.d("aidlPool:", "aidlPoolInterface is not null");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}
package com.example.wangqiubo.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;

import com.example.wangqiubo.myaidl.Book;
import com.example.wangqiubo.myaidl.IBooksAidlInterface;

import java.util.List;

/**
 * Created by wangqiubo on 2017/5/17.
 */

public class AidlPoolActivity extends Activity implements View.OnClickListener{
    private IBooksAidlInterface booksAidlInterface = null;
    private ListView mListView = null;
    private Button addBook = null;
    private Button queryBinder = null;
    private MyHandler mHandler = null;
    private AidlPool mAidlPool = null;
    private CustomBaseAdapter customBaseAdapter = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aidl_pool);
        mHandler = new MyHandler();
        mListView = (ListView) findViewById(R.id.my_list_view);
        customBaseAdapter = new CustomBaseAdapter(this);
        mListView.setAdapter(customBaseAdapter);

        addBook = (Button)findViewById(R.id.update);
        addBook.setOnClickListener(this);
        queryBinder = (Button)findViewById(R.id.query);
        queryBinder.setOnClickListener(this);
        mAidlPool = new AidlPool(this);


    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private static final int ADD_BOOK_CODE = 0;

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.update){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Book book = new Book("乔布斯", "名人传", "1");
                    try {
                        booksAidlInterface.addBook(book);
                        book = new Book("雷军", "名人传", "2");
                        booksAidlInterface.addBook(book);
                        book = new Book("柳传志", "名人传", "3");
                        booksAidlInterface.addBook(book);
                        List<Book> books = booksAidlInterface.getBookList();
                        customBaseAdapter.setBookDatas(books);
                        Message msg = mHandler.obtainMessage();
                        msg.what = ADD_BOOK_CODE;
                        msg.sendToTarget();

                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                }
            }).start();
        }else if (v.getId() == R.id.query){
            try {
                IBinder binder = mAidlPool.queryBinder(AidlPool.BOOK_BINDER_ID);
                if (null != binder){
                    booksAidlInterface = IBooksAidlInterface.Stub.asInterface(binder);
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    private class MyHandler extends Handler{

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case ADD_BOOK_CODE:
                    customBaseAdapter.notifyDataSetChanged();
                    break;
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    }



}

本文由【waitig】发表在等英博客
本文固定链接:AIDL终极篇之AIDL架构设计
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)