浅析android系统设计中的回调思想
一、为何写作本文
在慢慢深入接触android开发的过程中,我越来越发现android中(至少应用曾的开发)用到了很多回调的思想。比如activity的生命周期,fragment的生命周期,皆是回调函数实现的,android中的事件处理机制其一就是回调,线程方面的异步任务、loader、hanlder等都是基于回调的,等等。
可见android的其一根本思想就是回调,需要你来参与时,回调用相关的回调方法,你来填充。
可以说回调的思想浸润与android设计的方方面面,android开发中几乎带有on的方法都是回调方法。作为一名致力于深入学习移动开发的菜鸟,深入理解回调就显得非常必要了。
二、为何要引入回调
回调是不得以而为之的设计策略,想象一种系统实现:在一个下载系统中有一个文件下载模块和一个下载文件当前进度显示模块,系统要求实时的显示文件的下载进度,想想很简单,在面向对象的世界里无非是实现两个类而已。但是问题恰恰出在这里,显示模块如何驱动下载进度条?显示模块不知道也不应该知道下载模块所知道的文件下载进度(面向对象设计的封装性,模块间要解耦,模块内要内聚),文件下载进度是只有下载模块才知道的事情,解决方案很简单给下载模块传递一个函数指针作为回调函数驱动显示模块的显示进度。
在面向对象的世界中这样的例子还真不少,造成这样的问题的根源,相信大家已经从上面的叙述中体会到了,就是面向对象的程序设计思想,就是设计模式中要求的模块独立性,高内聚低耦合等特性。
封装变化的编程策略给编程人员第一位的指导思想就是面向接口编程,即设计模式中提到的面向虚拟编程而不是面向实现。这样的编程思想极大地革新了编程世界,可以说没有这一原则就没有面向对象的程序设计,这一原则给程序设计一种指导思想:即如何更高的将现实模型映射成程序模型。这样的设计思想在极大地催生高度独立性模块的同时削弱了模块间的协作性,也就是耦合性,它使得模块间更多的从事着单向的调用工作,一个模块需要某种服务就去找另一个模块,这使得程序呈现出层次性,高层通过接口调用底层,底层提供服务。但是现实世界中严格遵循现层次特性的系统是很少见的,绝对的MVC是不存在的,因为更多的模块要求通并协作,可见没有耦合就没有协作没有好的调用关系,耦合真的不是错。
既然我们需要模块间的协作,同时我们又厌恶的摒弃模块间你中有我我中有你的暧昧关系那如何生成系统呢,答案是函数指针(不一定是函数指针)也就是使用回调的方式。如果一个对象关心另一个对象的状态变化那么给状态的变化注册回调函数让它通知你这类状态的改变,这样在封装了模块变化的同时实现了模块间的协作关系另辟独径的给对象解耦。
三、回调的通俗理解
你饿了,想吃饭,就一会去问你妈一声”开饭没有啊?”这就是正常函数调用.
但是今天你妈包饺子,花的时间比较长,你跑啊跑啊,就烦了.于是你给你妈说,我先出去玩会,开饭的时候打我手机.等过了一阵,你妈给你打电话说”开饭啦,快回来吃饭吧!”
其中,你告诉你妈打手机找你,就是个你把回调函数句柄保存到你妈的动作.你妈打电话叫你,就是个回调过程.
四、回调的详细解释
理解方式1:一般写程序是你调用系统的API,这个过程叫Call。如果把关系反过来,你写一个函数,让系统调用你的函数,那就是回调(CallBack)了,那个被系统调用的函数就是回调函数。放到android中,我们一般是调用framwork定义的api,但是如果我们写了一个方法,由framwork来调用,这个方法就是回调函数。
理解方式2:所谓回调函数,其运行方式是,“你不用调用我,等着我来调用你”。回调的意思是在你执行某个语句后成功了,再执行你传递进来的function,在做异步处理的时候特别有用。
理解方式3:归程序本质,刨除那些面向对象的概念,回调函数就是一个通过函数指针调用的函数。就是用函数指针做参数。那个函数指针就是回调函数。
回调是编程层面的设计模式,不是基于语言的。在C/C++中,要用回调函数,被调函数需要告诉调用者自己的指针地址,但在JAVA中没有指针,怎么办?我们可以通过接口(interface)来实现定义回调函数。在.Net的世界里Delegate ==Callback。
五、在android中怎么使用回调呢
JAVA的CALLBACK通过接口来实现。
例:
1.class A,class B
2.class A实现接口operate
3.class B拥有一个参数为operate接口类型的函数test(operate o)
4.class A运行时调用class B中test函数,以自身传入参数
5.class B已取得A,就可以随时回调A所实现的operate接口中的方法
六、简明案例
以妈妈喊儿子吃饭为例,贴代码如下:
//java实现回调,采用接口做回调函数
public interface CallBack {
void eat();
}
/*
*
* 儿子要去玩游戏,不肯乖乖坐在那里等饭做好。
* 所以,他需要先问妈妈饭做好了没?即正常函数调用 : call askMom()
* 没有就去玩游戏,等妈妈饭做好了,再来叫他吃饭即函数回调: callback eat()
*
*/
public class Son implements CallBack { //son持有mom的引用.
private Mom mom;
public void setMom(Mom mom){
this.mom = mom;
} public void eat() {
System.out.println("儿子:我来吃饭了");
} public void askMom(){
//通过对mom的引用调用含有接口参数的方法
System.out.println("儿子:饭做好了吗"); System.out.println("儿子:没做好的话,我去玩游戏了"); new Thread(new Runnable() { @Override
public void run() { mom.doCook(Son.this); }
}).start(); }
}
/*
* 调用回调函数的对象:妈妈
*/
public class Mom {
public void doCook(final CallBack callBack){
new Thread(new Runnable() { public void run() {
System.out.println("妈妈:还没做好...."); try { Thread.sleep(5000);
System.out.println("\n");
System.out.println("------5秒后------");
System.out.println("妈妈:饭做好了,儿子快过来吃饭了");
//调用回调函数,喊来儿子来吃饭
callBack.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
/*
* 测试案例
*/
public class Test { public static void main(String[] args) { Mom mom = new Mom();
Son son = new Son(); son.setMom(mom);
son.askMom(); } }
运行结果: 儿子:饭做好了吗
儿子:没做好的话,我去玩游戏了
妈妈:还没做好.... ------5秒后------
妈妈:饭做好了,儿子快过来吃饭了
儿子:我来吃饭了
七、回调用在哪里
回调函数主要用于一些比较费时的操作,或响应不知道何时将会发生的事件,场合异步结合(异步其实就是重开一个线程)。
当两个对象之间需要进行一些协同操作时,常使用回调函数,比如一个对象想获得另一个对象内部的某些数据。
八、回调的优点
回调函数使得程序设计更加灵活。
实现模块独立性,将实现者和调用者分离,符合面对对象高内聚低耦合的设计思想。
九、回调的缺点
代码的易读性不好。
转载:https://blog.csdn.net/a910626/article/details/45920893
浅析android系统设计中的回调思想的更多相关文章
- 浅析Android设备中grep命令处理流程
2017-04-18 概述 在TV开发板中,可以在串口中直接使用grep命令.这是因为在/system/bin/下有一个'grep'链接.这个链接指向'/system/bin/toolbo ...
- 浅析Android Dialog中setContentView()方法
2017-05-15 概述 Dialog在Android中是一个很优秀的工具.在使用Dialog时,我们一般都会自定义要显示的内容布局.Dialog自带了三个方法来支持自定义内容布局. public ...
- 讨论Android开发中的MVC设计思想
最近闲着没事,总是想想做点什么.在时间空余之时给大家说说MVC设计思想在Android开发中的运用吧! MVC设计思想在Android开发中一直都是一套比较好的设计思想.很多APP的设计都是使用这套方 ...
- Android中关于回调概念的笔记
一.回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调 ...
- [原创]Android系统中常用JAVA类源码浅析之HashMap
由于是浅析,所以我只分析常用的接口,注意是Android系统中的JAVA类,可能和JDK的源码有区别. 首先从构造函数开始, /** * Min capacity (other than zero) ...
- Android中自定义veiw使用Java中的回调方法
//------------------MainActivity----中---------------------------------- import android.os.Bundle;imp ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
- android中的回调
1.引子 android中的回调最经典的就是点击事件设置监听(一般通过switch(v.getId()))这里写个最基本的 btn_rigister.setOnClickListener(new Vi ...
- ZT ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01
ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01 分类: 嵌入式 android framework 里java调用native,使用JNI机制,ja ...
随机推荐
- Android中在不同activity中进行自定义广播的解析
相信有不少人和我一样曾经尝试过在同一个项目中的两个activity进行广播,发现怎么都实现不了.我也是困惑了好久才发现,这么搞本来就是不行的.首先在同一个项目下不同的activity之间广播没有意义, ...
- MySQL之 视图,触发器,存储过程,函数,事物,数据库锁,数据库备份
1.视图 视图: 是一个虚拟表,其内容由查询定义: 视图有如下特点; 1. 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系. 2. 视图是由基本表(实表)产生的表(虚表). 3. ...
- 启动一个SpringBoot的maven项目
最近拿到了一个maven项目,原先是使用.net开发的,虽然Java和C#的语法相近,但是难免还有一些差别,包括语言特性,IDE的使用方面,都需要一段时间的习惯和适应. 该项目总体上是前后端分 ...
- HTML5外包团队 更新一下2019最新案例
本项目控件均为动态加载,3D部分使用Unity3D,其它基于ReactJS,NodeJS,部分使用cocos2D,由于项目涉密,只能发部分截图,欢迎联系索取更多案例,企鹅号 372900288 祝大家 ...
- Shiro 与spring 整合的及简单使用(转)
文章完全转载自: http://www.cnblogs.com/learnhow/p/5694876.html ,大家可以点击访问原文链接,个人仅作学习收藏 ! 本篇内容大多总结自张开涛的<跟 ...
- 一步一步搭建vue项目
1 安装步骤 创建一个目录,我们这里定义为Vue 在Vue目录打开dos窗体,输入如下命令:vue create myproject 选择自定义 4. 先选择要安装的项目,我们这里选择4个 5 ...
- 解决JS中取URL地址中的参数中文乱码
GET请求会将中文编码,如果取出乱码的话,应该进行解码操作, 下面的函数是获取指定参数名的参数值,参数值可是中文.英文. function getQueryString(name) { var reg ...
- CORS在Spring中的实现
CORS: 通常情况下浏览器禁止AJAX从外部获取资源,因此就衍生了CORS这一标准体系,来实现跨域请求. CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origi ...
- Django的form表单
html的form表单 django中,前端如果要提交一些数据到views里面去,需要用到 html里面的form表单. 例如: # form2/urls.py from django.contrib ...
- jquery tab切换
首先引入jquery.js <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...