A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 武汉分校-小舞 于 2016-3-24 17:25 编辑

【武汉校区】独家分享:理解回调(Listener)

前言
学习安卓,大家接触的第一个Listener很可能就是View.OnClickListener,而且用起来也没有问题,很简单。但是如果要大家去写一个回调,可能大家就犯难了。
其实回调的书写非常简单,我在这里把它总结程了2个类、5个步骤:
·        2个类:
1.   定义了回调接口的类;
2.   实现了回调接口的类。
·        5个步骤分为:
定义了回调接口的类:
1.  定义一个回调接口,并对接口制定方法签名(方法名、返回值、参数),暂时称为**XxListener**
2.  对外提供传入实现了此接口的对象的方法,称为*setXxListener*,并记录为成员变量,叫做**xxListener**
3.  在合适的时机调用回调对象的方法,一般会检查是否为空

实现了回调接口的类:
1.  实现**XxListener**,完成接口规定的方法,称为**myXxListener**
2.  把此对象通过*setXxListener*方法,传递给上面的类。

理解回调
为了便于理解,我们举一个常见的购物的例子:
我(称作客户)在京东下订单买了一本书(《金瓶梅》),因为书是一个实物,所以必须经过快递员的配送才能到我手中,那么这里就几个关键概念:京东、客户、订单,其实快递员可以理解为京东的一部分。
我们来看一下这些步骤:
1.   客户填写订单,这个订单的格式是京东规定的;
2.   客户提交订单,京东提供了提交订单的方法;
3.   京东准备货物,在一段时间之后,让快递员送货,当快递员将要送到的时候,拨打订单上的电话,通知我,书到了,然后客户顺利的拿到了《金瓶梅》。

在上述步骤1中:
大家首先可以把京东理解为定义了回调接口的类,因为订单的格式是京东规定的;
那这个接口就是订单格式;
而客户呢,就是实现了订单接口的类(不是直接实现,而是客户的成员变量中有实现了订单接口的对象),具体表现是:填写订单。

在上述步骤2中:
客户调用京东的提交订单的方法,把实现了订单接口的对象(填写完成的订单)传递给了京东。

在上述步骤3中:
京东在货物快要送达的时候,调用之前传入的订单对象上的方法(拨打电话,通知货到了)。
如果理解了这个例子,我们再看一下ViewOnClickListener
·        Activity是实现了OnClickListener接口的类;
具体的activity,实现了OnClickListener,并调用具体的viewsetOnclickListener方法,onClickListener传递给了View
·        View是定义了OnClickListener接口的类;
那view对象做了什么呢?它通过分析落在自己身上的触摸事件,发现属于点击行为,就去检查一下是否具有点击监听,如果发现有就调用一下上面的onClick方法,并且对方法中传递自身作为参数并调用,让activity知道那个view被点击了。而我们的具体实现呢,可能是显示一个土司、打印一段日志、播放动画、下载数据都可以。
问答环节:
1.    那为什么使用回调呢?
就是因为在定义View之初,并不知道点击后具体有哪些事情要做,所以让其他的类告诉view做什么,view在发现点击后调用一下即可。主要目的在设计上提供接触耦合性,为程序的扩展性提供帮助。
2.    那么什么时候该使用回调?
想知道某件事件发生了,要进行进一步处理;但不知道该事件具体什么时候发生时使用。比如说,你肯定不知道用户在什么时候点击一个Button,但你知道用户根据界面点击Button后想完成什么操作,就可以对Button设置点击回调监听。
3.    那么监听和Callback是什么关系呢?比如说XUtilsHttpUtils的send方法中的Callback
就具体来说,Callback是回调的一种,在这个具体例子中有以下几点:
1.   一次请求一般对应一次Callback,而设置了点击监听后,可以被多次调用
2.   Callback包含子线程和主线程的切换,也就是说在主线程中不能下载,在子线程中不能改UI
3.   Callback实际上是:在子线程中完成了下载(耗时),然会利用Handler,把下载好的数据传入到主线程中,让主线程完成更改界面操作
4.    more
总结和提高
其实回调并不其他步骤都不难,最难的其实就是定义接口和接口上的方法,因为接口的中的方法确定了,那么了什么时候调用方法也是知道的,至于setXxListener方法更加是固定写法;接口中的方法定义,涉及的参数(几个、什么类型的返回值才刚好够用而又不嫌多余)、返回值(返回值到底是void 、boolean、int还是其他对象)才是最关键的。
大家编程之初,可能听过技术经理就是定义一些接口,具体实现都由开发人员完成,一定会决定技术经理的工作很轻松,但是这需要对业务、程序的深入理解才能胜任。
在学java时,对面向对象的概念懵懵懂懂,在写代码时常常会写面向过程的代码;而面向接口编程就是在掌握面向对象思想后的另一个境界。
一般来说,接口回调的设置回调对象方法是setXxListener,但是这样写就意味着只能接受1个监听,那么京东类肯定不能这样设计,不能之服务于一个客户。还有一种写法就是addXxListener,那么就可以记录多个回调对象。以我们熟悉的ViewPagerOnPageChangedListner为例,原先大家都写setOnPageChangedListener,在后来的support-v4包中,谷歌把此方法添加为过时,并提供了addOnPageChangedListener方法。因为google发现,有时候在OnPageChangedListner需要完成多种业务逻辑,如果代码混在一起,可读性就很差。
但是需要注意的是,如果有addXxListener方法,就一定要写removeXxListener方法,让外界调用,避免内存泄漏。但有时候,外界就是忽略了removeXxListener,那我们还不能直接使用普通的List或是Set集合去记录监听回调对象,而是应该使用软引用,避免内存泄漏和提高垃圾回收的及时性。

想获取最新传智播客武汉中心分享技术文章请加QQ  1641907557 ,后期会分享更多与实体班同步教程,助你冲击月薪20K!

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马