缘起
首先,我对软件开发这个工种有一个基本认识,即软件是人写得,人是活在现实世界里的。人们编写软件其实只是把自己的想法转换成代码,继而交给计算机来执行而已。而人类的想法是不能脱离我们对世界的认识。很简单的一个例子,猪、狗等动物的想法肯定和人不一样。
-
信息传递的角度:我们会先表明现实世界中的场景。
-
Android中的广播和Binder:是讲现实世界中的场景如何映射到Android开发中。
我一直说“基于Android,高于Android”,“基于Android”要求我们了解,摸清楚“术”,“高于Android”则是提醒大家注意具体“术”背后的“理”。只有真切掌握了“理”,未来再出现什么OS,大家都不用担心了——小样,别以为你穿上马甲我就不认识你了。
整体视频
由PPT转换而来的视频
上面视频里介绍了8个部分,分别是:
-
信息传递——古已有之
-
信息传递——生活中的场景
-
信息传递场景A——广播
-
Android中广播的实现
-
信息传递场景B——过程调用
-
远程过程调用的三个问题
-
Android中的Binder
-
回归信息传递的本质——一个简单的Binder框架commonRPC
每个部分都不长。大家可以先看下面的内容,等整体看完后,再来看上面的PPT视频。
信息传递——古已有之
上面这个图来自一个视频,如下:
信息传递——生活中的场景
现在来看看生活中的两个场景。
这个图使用了前些年很火的一个案例,我做了一些拓展:
-
原文是“贾君鹏,你妈妈喊你回家吃饭”。这个case就是广播,发送者是否认识贾君鹏strong>不care。贾君鹏能不能收到这条消息strong>也不care。
-
拓展case则变成“@贾君鹏,你妈妈喊你回家吃饭”。在贾君鹏名字前多了一个@符 ,以微博来说,这就是直接给贾君鹏发信息了。我们姑且将这个case称为过程调用。
先来看信息传递的第一种场景。
信息传递场景A——广播
看下图:
上图是生活中广播的场景映射到Android平台上的情况。简单来看,广播包括两个基本特点:
-
发送者只管发消息,不care谁接收。
-
接收者只关注自己感兴趣的消息。所以,在贾君鹏回家吃饭的案例中,和贾君鹏认识,或者可能知道他的人才会对那个消息有所动作。
上面这个信息传递的案例映射Android世界中会产生什么就很清楚了:
-
首先要提供广播发送的功能,即Context sendBroadcast系列API。
-
然后要提供接收广播的功能,其中最重要的就是把对哪些广播感兴趣的这个信息表达清楚。
Android中广播的实现
现在来具体看看Android中广播的实现,我将它分为基础功能和高级玩法两个部分。先看基础功能:
上图,Android中的广播机制还有几种高级玩法:
-
A 群发广播,无优先级之分。注意,这条其实是基本玩法了。作为对比,我单独列出来。
-
B 群发广播,但是有优先级之分,高优先级先接收广播,还能中断广播的后续发送。这个场景也很常见,比如很多重大消息都是先到高层,然后再传播到中低层,或者不传给中低层。
-
C 广播发了,但后来的接收者没收到。接收者说我就是得知道这个信息。怎么办想想现实生活中的解决办法,一定是有个地方存在,然后等你来的时候给你。所以,Android也是这么处理的。
以上是Android中的广播,现在我们来一个反向思考。
-
从信息传递的角度看,是不是大家(假设你是懂事的成年人)早就知道,体会,用过广播了然如此,到了Android,广播还有那么难吗些玩法,和现实生活中有什么不同/p>
再者,除了Android Broadcast外,UDP组播、D-BUS、UEvent是不是也是可以用作广播/p>
-
最后,仔细观察广播的参与方——接收者和发送者,是不是就是Publisher/Subscriber模式,果然就是换了一个马甲。
信息传递场景B——过程调用
接着来看信息传递场景之二——过程调用。
上面这个图中,我把“@贾君鹏,你妈妈喊你回家吃饭”转换为一个函数。目的是告诉贾君鹏一个消息,这个动作可以转换成图中的sendMessage函数,其中:
-
mrJiaJunPeng:标识who,即消息的接收者。
-
tell:是我对贾君鹏发出的动作。大家不要忽略这个tell。因为不是所有人都能“tell”,比如,聋哑人朋友就是打手势,而不能说话。
-
具体的消息:你妈妈喊你回家吃饭
其中,最后两条——tell和具体的消息再拔高抽象一下,两者对mrJiaJunPeng来说可组合起来当做一个信息(现在是两个,一个是动作,一个是具体的信息)。
上面讲这么多有什么用呢着看
简单来看,过程调用有两种形式:
-
本地过程调用,也就是Caller(调用者)和目标(mrJiaJunPeng)在一个进程里。这其实就是函数调用。90%都是这样的。
-
远程过程调用:也就是Caller和目标不在同一个进程里。怎么办/p>
上面是一个比较实际的代码片段了。技术上的问题是如何实现远程过程调用。而从信息传递的角度看,其实只有下面三个问题:
-
发给谁/strong>
-
发什么内容/strong>
-
怎么发/strong>
下面我们来解决这三个问题。
远程过程调用的三个问题
我们先讨论“怎么发”的问题。这也是最能揭开诸多“马甲”的地方。来看下图:
上图介绍了“发给谁”和“发什么内容”的解决办法:
-
发给谁:socket/http/webservice是通过地址+端口 /url来标识目标的。而pipe、shared memory通过fd来标识目标。
-
发什么内容:两种办法,一种是像binder这样使用自定义的协议(协议中会包含交互的双方是谁,信息以什么格式封装等)。还有一种就是基于诸如http这样的标准协议之上来处理。
好了,Binder的本质已经揭露了,它和任何之前、现在已知的其它RPC方法都没有本质区别。不过,为何大家会觉得Binder难呢/strong>
Android中的Binder
我们为什么会觉得Binder难呢实话,Binder确实难。不过,为什么会这样看下图:
上图中:
-
Binder其实存在一个通讯层,只不过封装得比较好,你一般看不到罢了。信息还是先通过binder设备传到通讯层的onTransact函数。
-
在onTransact函数中,信息中包含了业务函数的code。根据这个code,找到对于的业务函数,调用它。
通过这种方式,通讯+业务完美结合。
Binder好用吗实话我觉得有点麻烦。接着来看。
图中,我们的解决思路就是:
-
commonRPC回归到通讯,不涉及业务。
-
作为通讯框架,它就提供call和notify两个函数。至于交互双方要发什么信息,完全由这两个函数的参数决定。
你可以把commonRPC看成HttpClient。当然,我们比HttpClient看起来高级一点,你还是能像本地函数一样调用。来看下图:
cmomonRPC的服务端和Binder的通讯层有些类似:
-
onCall是服务端收到客户端请求的入口。
-
onCall里,服务端解析参数,然后再去调用对应的业务函数。
说实话,commonRPC服务端其实是把Binder对大家隐藏在通讯层里干得事情又重新暴露在开发者眼前了。嗯,有时候封装太完美也让我们丧失了一些自由。
就我的情况来说,我们好些个APP的架构都差不多:
-
用户操作,给隐藏在后面的Service发请求。
-
Service再把请求HTTP发给后台。
-
后台处理请求,结果返回给Service,从而转给用户UI。
借助commonRPC,我们就可以打通UI到Service到后台的统一协议。例如,UI给Service发的请求和Service给后台发的请求一样——可能略有区别,但也不过是一些包装而已,核心的信息一定是一样的——毕竟,从UI到最终的后台,我们都是在传递信息,参与方是务必要保证信息的准确和一致的。
到此,我们对信息传递的第二个场景以及Binder也介绍完了。现在我们来看看最终的结论。
为什么我觉得少儿学习编程完全没必要/p>
IT,全称是Information Technology,信息科技。码农是属于IT行业里的,但我不知道有多少码农真切感受到自己在操作“信息”了
神农和朋友们的杂文集
长按识别二维码关注我们
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!