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);
}
};
}