Android多进程观察者模式

1.观察者模式简介

观察者模式(Observer)又叫做发布-订阅模式(Publish/Subscribe),定义对象之间的一对多关系,使得对象的状态发生改变的时候,所有依赖它的对象都会得到通知并且更新状态

2.多进程中观察者模式

单进程观察者模式的使用,在此不做介绍,我们继续 AIDL通信这个例子里面的代码,
首先定义一个aidl,文件IStudentListener.aidl

// IStudentListener.aidl
package cc.funeay.sepprocesswebview.aidl;

import cc.funeay.sepprocesswebview.aidl.Student;

// Declare any non-default types here with import statements

interface IStudentListener {
    /**
     * 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);
    void onStudentChange(in Student student);
}
    private List listeners = new ArrayList<>();//监听列表
    private StudentManager.Stub binder = new StudentManager.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        ...//此处省略一万字

       /**
         * 注册listener
         * @param listener
         */
        @Override
        public void registerListener(IStudentListener listener) throws RemoteException {
            if(!listeners.contains(listener)){
                listeners.add(listener);
            }
        }

        /**
         * 移除listener
         * @param listener
         * @throws RemoteException
         */
        @Override
        public void unRegisterListener(IStudentListener listener) throws RemoteException {
            if(listeners.contains(listener)){
                listeners.remove(listener);
            }
        }
    };

修改如下代码,当add完成以后调用监听者的方法

 @Override
 public void addStudentInout(Student s) throws RemoteException {
            //s.setName("update");
            students.add(s);
            //通知listener更新
            if(listeners != null){
                int size = listeners.size();
                for(int i = 0;i
//MainActivity.java实现IStudentListener接口 注册监听者
    private IStudentListener.Stub listener = new IStudentListener.Stub() {
        @Override
        public void onStudentChange(Student student) throws RemoteException {
            displayStudent(student);
        }
    };

我们运行一下,看到能正常地回调客户端的接口,但是解绑listener的时候发现listener不是原来的了,

public class StudentService extends Service {
    private List students = new ArrayList<>();
    private List listeners = new ArrayList<>();//监听列表

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

    /**
     * 实现StudentManager接口
     */
    private StudentManager.Stub binder = new StudentManager.Stub() {

...
        /**
         * 注册listener
         *
         * @param listener
         */
        @Override
        public void registerListener(IStudentListener listener) throws RemoteException {
            Log.d("addStudentIn","listener at " + listener);
            if(!listeners.contains(listener)){
                listeners.add(listener);
            }
        }

        /**
         * 移除listener
         * @param listener
         * @throws RemoteException
         */
        @Override
        public void unRegisterListener(IStudentListener listener) throws RemoteException {
            Log.d("addStudentIn","remove listener0 at " + listener);
            if(listeners.contains(listener)){
                Log.d("addStudentIn","remove listener at " + listener);//走不到这里 listener已经改变了
                listeners.remove(listener);
            }
        }
    };
}

这个时候就需要用到RemoteCallbackList,这个是支持跨进程的,修改后的完整代码

//StudentService.java
public class StudentService extends Service {
    private List students = new ArrayList<>();
    //private List listeners = new ArrayList<>();//监听列表
    private RemoteCallbackList remoteCallbackList = new RemoteCallbackList<>();//支持跨进程

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

    /**
     * 实现StudentManager接口
     */
    private StudentManager.Stub binder = new StudentManager.Stub() {

        @Override
        public void addStudentInout(Student s) throws RemoteException {
            //s.setName("update");
            students.add(s);
            onStudentListenerChange(s);
        }

        @Override
        public void addStudentIn(Student s) throws RemoteException {
            Log.d("addStudentIn", s.toString());
            s.setName("update");
            students.add(s);
            onStudentListenerChange(s);
        }

        private void onStudentListenerChange(final Student student) throws RemoteException {
            int count = remoteCallbackList.beginBroadcast();
            for (int i = 0; i < count; i++) {
                IStudentListener listener = remoteCallbackList.getBroadcastItem(i);
                if (listener != null) {
                    listener.onStudentChange(student);
                }
            }
            remoteCallbackList.finishBroadcast();
        }

        @Override
        public List getStudents() throws RemoteException {
            return students;
        }

        @Override
        public void clear(int isClear) throws RemoteException {
            students.clear();
        }

        /**
         * 注册listener
         *
         * @param listener
         */
        @Override
        public void registerListener(IStudentListener listener) throws RemoteException {
            Log.d("addStudentIn", "listener at " + listener);
            remoteCallbackList.register(listener);
            Log.d("addStudentIn", "listsize " + remoteCallbackList.beginBroadcast());
            remoteCallbackList.finishBroadcast();
        }

        /**
         * 移除listener
         * @param listener
         * @throws RemoteException
         */
        @Override
        public void unRegisterListener(IStudentListener listener) throws RemoteException {
            Log.d("addStudentIn", "remove listener0 at " + listener);
            remoteCallbackList.unregister(listener);
            Log.d("addStudentIn", "listsize " + remoteCallbackList.beginBroadcast());
            remoteCallbackList.finishBroadcast();
        }
    };
}
//MainActivity.java
public class MainActivity extends AppCompatActivity {

    private static final String BOOK_SERVICE_ACTION = "android.intent.action.StudentService";
    private Button btnStartService;
    private StudentManager studentManager;//从service进程获取的实例
    private TextView tvDisplay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        findViewById(R.id.tv_go_webview).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                goWebView();
            }
        });
        btnStartService = findViewById(R.id.btn_start_service);
        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tryStartService();
            }
        });
        findViewById(R.id.btn_add_book).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (studentManager != null) {
                    try {
                        Student student = new Student(1, "Student-" + System.currentTimeMillis());
                        studentManager.addStudentInout(student);
                        disPlayStudents(studentManager.getStudents());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
/*        findViewById(R.id.btn_add_book_out).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (studentManager != null) {
                    try {
                        Student student = new Student(1, "Student-" + System.currentTimeMillis());
                        //  studentManager.addStudentOut(student);
                        disPlayStudents(studentManager.getStudents());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });*/
        findViewById(R.id.btn_add_book_in).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (studentManager != null) {
                    try {
                        Student student = new Student(1, "Student-" + System.currentTimeMillis());
                        studentManager.addStudentIn(student);
                       // disPlayStudents(studentManager.getStudents());

                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        findViewById(R.id.btn_clear).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (studentManager != null) {
                    try {
                        studentManager.clear(1);
                        disPlayStudents(studentManager.getStudents());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        findViewById(R.id.btn_unregister).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(studentManager != null &&studentManager.asBinder() != null &&studentManager.asBinder().isBinderAlive()){
                    try {
                        studentManager.unRegisterListener(listener);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        tvDisplay = findViewById(R.id.tv_dispaly);
    }

    private void disPlayStudents(List list) {
        List students = new ArrayList<>();
        if (list != null) {
            students.addAll(list);
        }
        StringBuffer sbf = new StringBuffer("*************学生列表***********\n");
        if (students != null) {
            int size = students.size();
            for (int i = 0; i < size; i++) {
                sbf.append(" ");
                sbf.append(students.toString());
                sbf.append("\n");
            }
        }
        tvDisplay.setText(sbf.toString());
        //Log.d("disPlayStudents ", sbf.toString());
    }

    private void displayStudent(Student student){
        tvDisplay.setText(student.toString());
    }

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

    private void tryStartService() {
        String isConnected = btnStartService.getTag() != null ? btnStartService.getTag().toString() : "0";
        if ("0".equals(isConnected)) {
            //未连接
            startService();
        }
    }

    /**
     * 启动service
     */
    private void startService() {
        Intent intent = new Intent();
        intent.setAction(BOOK_SERVICE_ACTION);
        intent.setPackage(getPackageName());//Android 5.0开始不再支持 隐式启动service 需要写成包名
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 停止/解绑service
     */
    private void stopService() {
        if(studentManager != null &&studentManager.asBinder() != null &&studentManager.asBinder().isBinderAlive()){
            try {
                studentManager.unRegisterListener(listener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        unbindService(connection);
    }

    private void goWebView() {
        Intent intent = new Intent();
        intent.setClass(MainActivity.this, WebViewActivity.class);
        startActivity(intent);
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            studentManager = StudentManager.Stub.asInterface(iBinder);
            if(studentManager != null){
                try {
                    studentManager.registerListener(listener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            updateBtnStart();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //异常的时候才会回调
            try {
                studentManager.unRegisterListener(listener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            studentManager = null;
            updateBtnStart();
        }
    };

    private void updateBtnStart() {
        btnStartService.setTag(studentManager != null ? "1" : "0");
        btnStartService.setText(studentManager != null ? "已连接" : "未连接");
    }

    private IStudentListener.Stub listener = new IStudentListener.Stub() {
        @Override
        public void onStudentChange(Student student) throws RemoteException {
            Log.d("disPlay student", "student " + student);
            displayStudent(student);
        }
    };
}

你可能感兴趣的:(Android多进程观察者模式)