Rxjava前篇(一):观察者模式之接口回调
来源:互联网 发布:access2000数据库修复 编辑:程序博客网 时间:2024/06/01 10:52
如理解有误或者模棱两可的地方,欢迎指出。共同进步,一起成长!
前言:为什么要了解观察者模式?
- 最近准备入手retrofit就遇到了RxJava(由于入坑晚+公司框架太老以至于到现在才开始自学rxJava);RxJava的异步让人佩服,切换线程只需一行代码,序列化事件链式操作……各种Obsever、Observable于是引出了观察者模式。
- 熟悉接口回调的能很快看懂观察者模式。
PS:个人认为学以致用,研究茴香豆有几种写法没有意义,但是我们要知其所以然,只会调api就显得很Low了哇。当我们用api出现问题,或者不能满足需求的时候,我们就得往底层看,去看源码,弄懂实现原理。懂了,才敢放心的用各种操作拼凑起来满足自己的需求。
本篇主要分为:
- 通用接口回调套路
- view click回调事件简单分析
- 接口回调对象的传递(主要是单例模式)
正文:观察者模式先来看看接口回调
接口回调异步是怎么实现的?
接口注册、实现和接口调用分离
总的来说就分三步走:
1.定义一个接口(待实现的抽象方法)
2.实现接口并注册接口
3.调用接口方法(这里一般是一个类,拥有刚才定义的接口,并对外提供注册接口的方法)然后回调到实现接口的地方执行
下面以我们常用的点击事件回调看一下:
- 实现接口并注册接口
//at mainActivity bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.v("tag","ui主线程发送msg "+"当前线程: "+Thread.currentThread().getId()); testThread.mhandler.sendEmptyMessage(0); } });
跟进去看一下View.OnClickListener()接口,其实从这儿可以看到接口是在View内部的
- 定义一个接口
public interface OnClickListener { void onClick(View v); }
就一个很简单的抽象方法,接口方法默认是public abstract,可以省略
- 调用接口方法(简单分析下点击事件,不感兴趣的可以直接跳过performclick)
都是在view.class里面,方便查看省略了很多代码
可以看到点击事件经过事件分发机制,经过事件分发拦截处理,最后来到view的dispatchTouchEvent(不了解事件分发机制的同学可以自行google,后面有空也会分享一点心得)
public boolean dispatchTouchEvent(MotionEvent event) {//....................ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { result = true; //决定是否调用onTouchEvent } if (!result && onTouchEvent(event)) { //result如果为flase这里调用onTouchEvent result = true; }}//............
可以看到如果上面li.mOnTouchListener.onTouch(this, event)返回为true,result为true; resulet如果为true,往下就不会执行ontouchEvent(进而执行click)了。
这也是为什么在重写ontouch返回为true,对应view的click事件不会响应。
onTouchEvent里面会调用performClick。注意是action_up的时候才会调用哦,也就是手指头按下不会,松开才会回调click事件。不知道平时大家有没有注意,不知道的还不赶紧试试= =
public boolean onTouchEvent(MotionEvent event) {//........... case MotionEvent.ACTION_UP:if (!focusTaken) { if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); //====这里调用performClick } }}//...........
下面代码可以看到如果mlickListener不为null就可以执行onclick方法,回调到注册接口那里执行。当然对对象判空是一种意识,不然如果忘了注册接口,就不仅仅是不能触发回调,而是直接空指针异常闪退了。
//at View.class public boolean performClick() { final boolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); //=====这里调用接口的onclick result = true; } else { result = false; } sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); return result; }
虽然看起来代码很多,那是因为android为了实现各种view事件复杂逻辑的代码。我们自己的逻辑如果比较简单,直接获取到subject,然后通过它的接口调用一下方法就行啦。
贴一个自己写的简单接口回调demo
//接口CallBackInterface public interface CallBackInterface { void onCallBack();}//Subject.class public class Subject { private CallBackInterface callBackInterface; public void setCallBackInterface(CallBackInterface callBackInterface){ this.callBackInterface = callBackInterface; } public void notifyCallBack(){ if(callBackInterface != null) { callBackInterface.onCallBack(); } } //一般情况是在这个类调用notifyCallBack();比如突然断网、数据库更新等。如果在其他地方调用,需要获取到subject这个注册了接口的对象。}//mainActivityprivate Subject subject = new Subject(); //获取subjuect对象是重点subject.setCallBackInterface(new CallBackInterface() { @Override public void onCallBack() { Log.v("tag","at mainActivity 11111"); } });//secondeActivityprivate Subject subject; //这个subject要是mainActivity 注册的那个对象,比如用构造函数,set等方法传过来。subject.notifyCallBack();
其实我觉得接口回调3步走没什么毛病。主要是subject.setCallBackInerface()和subject.notifyCallBack()的subject要是同一个对象。
ps:不要觉得没对象就随便new一个……..FFFFFF
如果callBackInterface.onCallBack()在Subject类里面调用,那没什么毛病。如果是在其他地方调用,就要考虑下这个subject注册和调用的地方传递。
- 上面的demo可以用intent传,不过subject要可序列化,所有Subject要实现Parcelable接口。
- 普通的类也可以用构造函数传过去。
- 如果确定Subject对象只有一个(即单例),那么用单例模式是最方便的了。
- 其他方法(骚操作)
Subject换成单例就变成下面这样,注意看注释
/** * Created by Dynamic on 2017/11/2. */public class Subject { private static volatile Subject singleSubject; //volatile是由于jdk1.5之前的漏洞 private Subject(){ //构造函数私有,确保单例的关键 } public static Subject getInstance(){ if(singleSubject == null){ //懒汉式,只有需要用到它的时候才去new,不是一开始就new出来 synchronized (Subject.class){ //线程同步,避免多线程同时执行,new很多个出来(单例) if(singleSubject == null){ // 双重检查;因为同步块里面第一个null去new,执行完后,已经不为Nulll了 //如果singleSubject有了,后面的线程就没必要再去new了 singleSubject = new Subject(); } } } return singleSubject; } private CallBackInterface callBackInterface; public void setCallBackInterface(CallBackInterface callBackInterface){ this.callBackInterface = callBackInterface; } public void notifyCallBack(){ if(callBackInterface != null) { callBackInterface.onCallBack(); } }}
上面使用的是最安全的单例模式了,不管在什么地方哪个类里面,只需要Subject.getInstance,拿到的就一定是同一个subject,非常方便。
可能有人会问接口回调能干什么呢?
- 当然是异步啦。像上面的demo,mainActivity注册完接口后,就去干其他事情了,不用等着secondActiviy调用callBack。接口调用的回调通知回来的时候,才去处理回调。
- 类A(如网络管理类)的事件(wifi断开)回调到类B(数据库管理类)处理(入库断开的事件),就可以访问B的私有成员变量和方法了。(以前不知道接口回调,还是用的handler通信 == )
下一篇我会以自己的看法来讲述一下观察者模式:以前刚听到这个模式的时候,觉得被观察者好可怜,被围观。后面渐渐发现被观察者才是老大啊,所有信号都是它发的发出来的,然后一群观察者去响应。怎么说呢,就好像是大家(可以规划到一个类集合里面)都在干活。老板突然说了句发工资了,然后大家全部去响应领工资,而且每个员工各自领的工资不一样(每个观察者实现回调不一样)。
- Rxjava前篇(一):观察者模式之接口回调
- Rxjava源码浅析(一)观察者模式
- 观察者模式(设置回调接口)
- 谜之RxJava (一) —— 最基本的观察者模式(一,二,三,四,可以连看)
- java 中的观察者模式实现之接口回调
- 设计模式之观察者模式(一)
- 设计模式之观察者模式(一)
- 观察者模式->EventBus->Rxjava
- GOF之观察者模式(一)
- Java 观察者模式(类似于用接口实现回调)
- 接口回调与观察者模式
- Retrofit+Rxjava 网络请求的简单封装(一)(观察者模式)
- 观察者模式(一)
- 观察者模式(一)
- 观察者模式(一)
- 观察者模式(一)
- Unity3D设计模式之观察者模式(16)(一)
- 设计模式之观察者模式(Observer Pattern)(一)
- Caffe下使用draw_net.py绘制lenet网络结构图
- 素数环所有所有可能
- 每天回顾linux命令(which)
- Maven-打外部jar包
- 《代码大全 》pdf下载(内附下载地址)
- Rxjava前篇(一):观察者模式之接口回调
- Matlab资料
- 稀疏矩阵的转置,求和,乘积的C/C++实现。
- 【笔记】插入排序
- Oracle学习及常见问题的解决-day01
- Python-----集合
- 【unix学习】文件处理2—文件sort、cut命令
- 【Django】WIN10安装MySQL-python时遇到403 SSL is required
- Anaconda3.4.2配置pyspark环境,win7无hadoop