Android多進(jìn)程觀察者模式

1.觀察者模式簡介

觀察者模式(Observer)又叫做發(fā)布-訂閱模式(Publish/Subscribe),定義對(duì)象之間的一對(duì)多關(guān)系,使得對(duì)象的狀態(tài)發(fā)生改變的時(shí)候,所有依賴它的對(duì)象都會(huì)得到通知并且更新狀態(tài)

2.多進(jìn)程中觀察者模式

單進(jìn)程觀察者模式的使用,在此不做介紹,我們繼續(xù) AIDL通信這個(gè)例子里面的代碼,
首先定義一個(gè)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<IStudentListener> listeners = new ArrayList<>();//監(jiān)聽列表
    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 {

        }

        ...//此處省略一萬字

       /**
         * 注冊(cè)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);
            }
        }
    };

修改如下代碼,當(dāng)add完成以后調(diào)用監(jiān)聽者的方法

 @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<listeners.size();i++){
                    if(listeners.get(i) != null){
                        listeners.get(i).onStudentChange(s);
                    }
                }
            }
 }
//MainActivity.java實(shí)現(xiàn)IStudentListener接口 注冊(cè)監(jiān)聽者
    private IStudentListener.Stub listener = new IStudentListener.Stub() {
        @Override
        public void onStudentChange(Student student) throws RemoteException {
            displayStudent(student);
        }
    };

我們運(yùn)行一下,看到能正常地回調(diào)客戶端的接口,但是解綁listener的時(shí)候發(fā)現(xiàn)listener不是原來的了,

public class StudentService extends Service {
    private List<Student> students = new ArrayList<>();
    private List<IStudentListener> listeners = new ArrayList<>();//監(jiān)聽列表

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

    /**
     * 實(shí)現(xiàn)StudentManager接口
     */
    private StudentManager.Stub binder = new StudentManager.Stub() {

...
        /**
         * 注冊(cè)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已經(jīng)改變了
                listeners.remove(listener);
            }
        }
    };
}

這個(gè)時(shí)候就需要用到RemoteCallbackList,這個(gè)是支持跨進(jìn)程的,修改后的完整代碼

//StudentService.java
public class StudentService extends Service {
    private List<Student> students = new ArrayList<>();
    //private List<IStudentListener> listeners = new ArrayList<>();//監(jiān)聽列表
    private RemoteCallbackList<IStudentListener> remoteCallbackList = new RemoteCallbackList<>();//支持跨進(jìn)程

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

    /**
     * 實(shí)現(xiàn)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<Student> getStudents() throws RemoteException {
            return students;
        }

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

        /**
         * 注冊(cè)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進(jìn)程獲取的實(shí)例
    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<Student> list) {
        List<Student> students = new ArrayList<>();
        if (list != null) {
            students.addAll(list);
        }
        StringBuffer sbf = new StringBuffer("*************學(xué)生列表***********\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();
        }
    }

    /**
     * 啟動(dòng)service
     */
    private void startService() {
        Intent intent = new Intent();
        intent.setAction(BOOK_SERVICE_ACTION);
        intent.setPackage(getPackageName());//Android 5.0開始不再支持 隱式啟動(dòng)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) {
            //異常的時(shí)候才會(huì)回調(diào)
            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);
        }
    };
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容