浅析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 ...
随机推荐
- 机器学习总结(一) Adaboost,GBDT和XGboost算法
一: 提升方法概述 提升方法是一种常用的统计学习方法,其实就是将多个弱学习器提升(boost)为一个强学习器的算法.其工作机制是通过一个弱学习算法,从初始训练集中训练出一个弱学习器,再根据弱学习器的表 ...
- L1,L2正则化代码
# L1正则 import numpy as np from sklearn.linear_model import Lasso from sklearn.linear_model import SG ...
- linux编译链接找不到库文件的解决方法。
今天编译出现ld: 0706-006 Cannot find or open library file: -l xerces-c_static,ld:open(): A file or directo ...
- Java对象、引用、实例
https://blog.csdn.net/zmx729618/article/details/54093075
- 64位 windows2008 R2 上安装32位oracle 10g 的方法
首先,我们要解除oracle安装的windows版本检测1.编辑安装包内文件 database\stage\prereq\db\refhost.xml 在 <OPERATING_SYSTEM& ...
- 【HNOI 2016】大数
Problem Description 小 B 有一个很大的数 \(S\),长度达到了 \(N\) 位:这个数可以看成是一个串,它可能有前导 \(0\),例如 00009312345 .小 B 还有一 ...
- css中绝对定位和相对定位的区别
先说个技巧一般用:子绝父相,即相对定位是给父级的,绝对定位的时候是给子级的. 一:绝对定位 position: absolute;绝对定位:绝对定位是相对于元素最近的已定位的祖先元素(即是设置了绝对定 ...
- swift 有道 翻译文档(1 定义变量常量,数组字典)
使用let来创建常量,使用var来创建变量.一个常量的值在编译时不需要知道,但是您必须为它指定一个值一次.这意味着您可以使用常量来命名一个您确定一次的值,但是在许多地方使用它.var myVariab ...
- photoKit使用笔记
@主要用到的类 1PHAssetCollection:图片资源数组(代表着相簿数组) 作用:获取相簿资源数组 示例代码: //获取相簿资源 PHFetchResult<PHAssetCollec ...
- NetSec2019 20165327 Exp2 后门原理与实践
NetSec2019 20165327 Exp2 后门原理与实践 快速找到重点: (1)使用netcat获取主机操作Shell,cron启动 (0.5分) (2)使用socat获取主机操作Shell, ...