进程间通讯回调客户端

首先进程间通讯的方式有:广播,ContentProvider(内容提供者),AIDL(Android接口定义语言)
今天我们所讲的就是AIDL:
首先定义AIDL接口文件,如果进程间要传递对象,那么这个对象必须实现Praceable接口:

// Book.aidl
package com.example.aidl;

parcelable Book;

远程服务端的方法,当图书变化的时候通知给监听者

package com.example.aidl;

import com.example.aidl.Book;
import com.example.aidl.IOnNewBookArriverdListener;

interface IBookManager {
	List<Book> getBookList();
    void addBock(in Book book);
    void registerListener(IOnNewBookArriverdListener listener);
    void unregisterListener(IOnNewBookArriverdListener listener);
}

监听器接口

package com.example.aidl;

import com.example.aidl.Book;

interface IOnNewBookArriverdListener {
	 void onNewBookArrived(in Book newBook);
}

Book类,注意:Book类所在的包名

package com.example.aidl;

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

public class Book implements Parcelable {
    private int no = 0;
    private String name;

    public Book(int no, String name) {
        this.no = no;
        this.name = name;
    }

    protected Book(Parcel in) {
        no = 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];
        }
    };

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

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

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

服务端需要注意的是:存储监听器的类是RemoteCallbackList

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;

import com.example.aidl.Book;
import com.example.aidl.IBookManager;
import com.example.aidl.IOnNewBookArriverdListener;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

public class BookManagerService extends Service {
    private static final String TAG = "BookManagerService";
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
//    这种写法,当解绑服务的时候,服务端竟然无法找到我们之前注册的那个listener,在客户端我们注册和解注册的时候
//    明明传递的是同一个 Listener啊!,最终服务端无法找到要解除的listener,而宣告失败,这当然不是我们想要的结果.
//    因为Binder会把客户端传递过来的对象重新转化并生成一个新的对象,虽然我们注册和解注册的过程传递的是同一个对象
//    但是,通过Binder传递到服务端之后,却会产生两个全新的对象,别忘了对象是不能跨进程传递的,对象的跨进程传递本质上
//    反序列化的过程,这就是为什么AIDL中的自定义对象都必须要实现Parcelable接口的原因,
//    那么我们如何才能实现解注册的功能呢?答案是 RemoteCallbackList,

    //        private CopyOnWriteArrayList<IOnNewBookArriverdListener> mListenerList = new CopyOnWriteArrayList<>();
    private RemoteCallbackList<IOnNewBookArriverdListener> mListenerList = new RemoteCallbackList<>();

    public BookManagerService() {
    }

    private void onNewBookArrived(Book book) throws RemoteException {
        mBookList.add(book);
        System.out.println("lgj service mBookList size:" + mBookList.size());
//        for (int i = 0; i < mListenerList.size(); i++) {
//            IOnNewBookArriverdListener listener = mListenerList.get(i);
//            listener.onNewBookArrived(book);
//        }
        int N = mListenerList.beginBroadcast();
        for (int i = 0; i < N; i++) {
            IOnNewBookArriverdListener broadcastItem = mListenerList.getBroadcastItem(i);
            if (broadcastItem != null) {
                broadcastItem.onNewBookArrived(book);
            }
        }
        mListenerList.finishBroadcast();
    }

    private Binder mBinder = new IBookManager.Stub() {

        @Override
        public List<Book> getBookList() throws RemoteException {
            System.out.println("lgj service Binder pid:" + android.os.Process.myPid() + " tid:" + Process.myTid());
            return mBookList;
        }

        @Override
        public void addBock(Book book) throws RemoteException {
            mBookList.add(book);
        }


        @Override
        public void registerListener(IOnNewBookArriverdListener listener) throws RemoteException {
//            if (!mListenerList.contains(listener)){
//                mListenerList.add(listener);
//            }else {
//                System.out.println(TAG + "lgj already exists...");
//            }
//            System.out.println(TAG + "lgj service register listener size :" +mListenerList.size() );

            mListenerList.register(listener);
            System.out.println(TAG + "lgj service register listener size :" + mListenerList.getRegisteredCallbackCount());

        }

        @Override
        public void unregisterListener(IOnNewBookArriverdListener listener) throws RemoteException {
//            if (mListenerList.contains(listener)){
//                mListenerList.remove(listener);
//            }else {
//                System.out.println(TAG + "lgj service not found,can not unregister...");
//            }
//            System.out.println(TAG + "lgj service unregister listener size :" +mListenerList.size());
            mListenerList.unregister(listener);
            System.out.println(TAG + "lgj service unregister listener size :" + mListenerList.getRegisteredCallbackCount());
        }
    };


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

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("lgj service BookManagerService onDestroy...");
        mIsServiceDestoryed.set(true);
    }

    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);

    @Override
    public void onCreate() {
        super.onCreate();
        // 模拟每隔5秒钟图书发生变化
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!mIsServiceDestoryed.get()) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int bookId = mBookList.size() + 1;
                    Book book = new Book(bookId, "new book#" + bookId);
                    try {
                        onNewBookArrived(book);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

客户端代码:

        Intent intent = new Intent(this, BookManagerService.class);
//        startService(intent); 长期运行在后台,
//        如果只是简单的bind没有start的话,那么退出Activity 服务也会随之而停止,
//        我理解Activity绑定服务的话,随着Activity的存在即服务而存在,随着Activity的销毁服务则停止
//        (即使你在Activity的onDestroy方法中没有调用unbindService() 这个方法,服务也会停止)
        bindService(intent,connection, Context.BIND_AUTO_CREATE);
     private IOnNewBookArriverdListener mListener = new IOnNewBookArriverdListener.Stub() {
        @Override
        public void onNewBookArrived(Book newBook) throws RemoteException {
            System.out.println("lgj xinshu : " + newBook.getName());
        }
    };

    public IBookManager mBookManager;
    ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBookManager = IBookManager.Stub.asInterface(service);
            if (mBookManager != null){
                try {
                    //添加注册监听实例对象
                    mBookManager.registerListener(mListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

注意ondestroy记得取消注册监听

    @Override
    protected void onDestroy() {
        try {
            mBookManager.unregisterListener(mListener);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
//        unbindService(connection);
        super.onDestroy();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值