记得之前我有写过一个接口回调的文章,那时候我也是只对观察者模式做了一个简单的甚至是投机取巧的解释,很多深层次的原理并没有点破,但事实上好像观察者模式也没什么深奥的地方,看了很多设计模式,其实最重要的一点就是遵循依赖倒置原则。如果你对依赖倒置原则有深刻的理解,那么很多设计模式应该就可以很快的去理解了。
在这个版本任务迭代里有一个需求是申请退款页面的开发,任务要求是在该页面完成申请操作后返回上一级页面要通知其进行刷新操作,比如订单详情页进入申请退款页面,当用户申请成功后返回订单详情页面需要刷新订单详情的接口,很常规的一个逻辑操作,处理方法也很多,比如startActivityForResult,比如用EventBus,但是我们业务间的跳转为了解耦是用URL规则跳转的,同时我要是为了完成返回刷新操作我还要额外的增加参数去标记一下,为了代码和逻辑的最原始性,我并没有这么做。
用EventBus也可以,但是有点大牛拉小车的感觉,一是浪费,二是项目也不推荐用这种方式,所以就没有考虑。
既然这样,我们只能自己实现一个乞丐版本的EventBus了,原理很简单,其实就是观察者模式。
首先我们要新建一个观察者的管理类去统一处理注册的观察者,代码如下
/**
* Created by lyd10892 on 2016/11/17.
* 单例模式。观察者管理类
*/
public class ObserverManger {
private List<ObserverManger.IListener> list = new ArrayList<>();
/***
* 私有化构造方法
*/
private ObserverManger(){}
private static class SingleInstance{
public static ObserverManger INSTANCE = new ObserverManger();
}
public static ObserverManger getInstance(){
return SingleInstance.INSTANCE;
}
/**
* 注册观察者
* @param listener
*/
public void registListeners(IListener listener){
if (!list.contains(listener)){
list.add(listener);
}
}
/**
* 移除观察者
* @param listener
*/
public void unRegistListener(IListener listener) {
if (list.contains(listener)) {
list.remove(listener);;
}
}
/***
* 通知刷新
*/
public void notifyOthersChanged(){
for (IListener listener : list) {
if (listener != null) {
listener.notifyDataSetChanged();
}
}
}
/**
* 定义接口,通知刷新
*/
public interface IListener{
void notifyDataSetChanged();
}
}
可以看到,管理类特别简单就是添加和移除观察者。
使用方法,如果你对EventBus很熟悉的话,使用上很类似,几乎一样的,代码如下:
public class MainActivity extends AppCompatActivity implements ObserverManger.IListener{
private TextView mJumpView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mJumpView = (TextView) findViewById(R.id.jump);
mJumpView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
jumpToSecondActivity();
}
});
ObserverManger.getInstance().registListeners(this);
}
private void jumpToSecondActivity() {
Intent intent = new Intent();
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
@Override
public void notifyDataSetChanged() {
Toast.makeText(MainActivity.this,"上个页面通知我刷新了",Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
ObserverManger.getInstance().unRegistListener(this);
}
}
只需要在你需要刷新的页面注册一下监听,实现刷新方法即可,剩下的就是交给B页面处理了,B页面很简单,我们现在只是处理为在返回上一级页面的时候刷新页面,所以,代码如下:
/**
* Created by lyd10892 on 2016/11/16.
*/
public class SecondActivity extends Activity {
private TextView mJumpView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
mJumpView = (TextView) findViewById(R.id.jump);
mJumpView.setText(this.getTaskId()+"");
mJumpView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// jumpToThirdActivity();
}
});
}
private void jumpToThirdActivity() {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(SecondActivity.this,SecondActivity.class);
startActivity(intent);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(SecondActivity.this,"onNewIntent被调用",Toast.LENGTH_SHORT).show();
}
@Override
public void onBackPressed() {
super.onBackPressed();
ObserverManger.getInstance().notifyOthersChanged();
}
}
在 onBackPressed方法里我们调用notifyOthersChanged()方法即可,就这样,我们的任务完成了,看一下效果:
效果还是很不错的。如果你要将当前页面的一些处理值返回给上一级页面,只需要在接口方法里增加相应参数即可,建议是Object,还是那句,依赖倒置原则。
写到这里我们的任务就算完成了,其实仔细想想,这个和接口回调很像,其实我一直没有搞清楚观察者模式和接口回调到底有什么不同之处,如果真的有,那就是观察者是一对多,接口回调是一对一吧。
观察者模式在我们代码里用的特别多,像最常用的Listview的刷新就是观察者模式的应用,好好学一下这个模式,简直就是解耦利器。
代码已经提交至github
https://github.com/nbwzlyd/GuanChaZheDemo
欢迎star