android framework学习(知乎-作者van Bruce)
首先放个地图炮,任何光讲源码的书都是耍流氓,无一例外。作者或许是大神,或许对于每一个地方的每一处源码都烂熟于心,但并不代表他们可以写出一部好书。原因很多时候在于,Android的功夫,在Android之外。这是理解Android源码的“道”,也是我近几年来愈发强烈的感受。
至于“术”,我只想说大神博客也好,书也好,90%的讲述方式都是错误的——作者展示出Android源码,然后告诉你这段是干嘛的,然后下一段……这样的书或博客,我个人看得非常痛苦,一开始我不明白为什么,工作了第三年,猛然明白,读起来痛苦的原因是倒转了因果。
几乎所有代码or模块or系统的开发初衷,都是为了解决某一问题。如果你光看源码,哦这个是干嘛的,那里调用了哪个API,这样看毫无意义,这样的所谓“讲解”书也毫无意义。大把的《深入XXX》实际上都没有深入,因为他们并没有搞清或说清,这里有个什么样的问题,而这个部分模块or源码怎样解决了这个问题,以及曾经其余的系统上如何解决这个问题——更有甚者,他们讲完解决方案,然后再编个问题出来,且说的好像这个问题只有这唯一一种方案可解一样……
就比如题主和很多答主提到的Binder机制,所有人都能说出来它是跨进程通信用的,可是你依然会看得想要吐血。包括很多blog讲起这部分,都有一种先有答案后编个问题出来的嫌疑,理解并不深入(尤其是上来就将Media部分的,大部分根本只讲了“怎么用”,完全没有“为什么”的部分,这也好意思起名字叫“深入理解XXX”)。
你想搞明白,首先要忘了Binder。然后想想看,有什么样的方案实现一个跨进程通信的方式?最容易想到的,一个是“共享内存”的方式或是“共享磁盘文件”的方式。其余的方式呢?
想不到去看看旧有的Linux系统上的演变过程,当你看到管道(Pipe)方式的实现,就会开始恍然大悟——原来还可以通过这样。然后你会更加理解UDS(Unix Domain Socket,非TCP/IP里面的那个socket,很多人会困惑与此)的出现,此刻你心里对于Server-Client端互相建立起IPC链接的过程才将变得明朗,甚至可以推出RPC(Remote Procedure Calls)的实现模型。
到这里,你再去看Binder的实现,从宏观的模型开始,一切都变得异常清晰起来。对于Binder Client和Binder Service各自的角色有了理解,Binder驱动与ServiceManager的联动,就变得更加清楚——和UDS或者RPC是不是很类似?甚至更容易理解一些,如果更加抽象的形容,ServiceManager就像DNS一样,负责Client查询到BinderService的IP地址(这也就理解了为何ServiceManager的通信标志恒为0),而Binder驱动则是路由器的角色。
然后细化下去,针对每一个模块本身的职责,询问更细节的实现,永远记住,先有的问题,之后才有的代码——这样才能理解为何Parcel是必要的(跨进程通信的高效序列化数据载体),为何IBinder或BpBinder是必须的,AIDL又是什么用——代码实现是新鲜的,但是有了之前的铺垫和对问题的预期,它们的出现才是可理解的。这是理解Android源码之“术”。
当然,说起来容易,做起来难。
整套模块看下来,抛开信息检索能力不谈,你需要补一些C++的基础,需要补计算机系统的基础,甚至需要理解设计模式——但不是说你成为任何一方的专家才能理解,只是随着一点点深入问题,随时去补课罢了。所以说跳着看书的能力是必须的,不是你想不想或者喜不喜欢的问题,它就是必须的——你唯一的问题就是愿不愿意让自己适应它,还是找个借口绕路。
所以这个问题又回到了最初提出的观点——Android的功夫,在Android之外。你要想“理解”而非单纯的“知道”,想“学习”而非单纯的“记诵”,我觉得没有他路可走。
总结起来就是:
先理解模块对应的要解决的“问题”是什么,再去给问题找解决方案的思路去理解源码。
理解源码的功夫不止在Android本身,也要提高Android之外的姿势水平。
最后,继续鄙视那些玩了几个app、听说Android开发语言用Java就对Android嗤之以鼻的自大狂们——对于Android这个庞大的知识库来说,90%的人离入门都还差得远呢。
至于“术”,我只想说大神博客也好,书也好,90%的讲述方式都是错误的——作者展示出Android源码,然后告诉你这段是干嘛的,然后下一段……这样的书或博客,我个人看得非常痛苦,一开始我不明白为什么,工作了第三年,猛然明白,读起来痛苦的原因是倒转了因果。
几乎所有代码or模块or系统的开发初衷,都是为了解决某一问题。如果你光看源码,哦这个是干嘛的,那里调用了哪个API,这样看毫无意义,这样的所谓“讲解”书也毫无意义。大把的《深入XXX》实际上都没有深入,因为他们并没有搞清或说清,这里有个什么样的问题,而这个部分模块or源码怎样解决了这个问题,以及曾经其余的系统上如何解决这个问题——更有甚者,他们讲完解决方案,然后再编个问题出来,且说的好像这个问题只有这唯一一种方案可解一样……
就比如题主和很多答主提到的Binder机制,所有人都能说出来它是跨进程通信用的,可是你依然会看得想要吐血。包括很多blog讲起这部分,都有一种先有答案后编个问题出来的嫌疑,理解并不深入(尤其是上来就将Media部分的,大部分根本只讲了“怎么用”,完全没有“为什么”的部分,这也好意思起名字叫“深入理解XXX”)。
你想搞明白,首先要忘了Binder。然后想想看,有什么样的方案实现一个跨进程通信的方式?最容易想到的,一个是“共享内存”的方式或是“共享磁盘文件”的方式。其余的方式呢?
想不到去看看旧有的Linux系统上的演变过程,当你看到管道(Pipe)方式的实现,就会开始恍然大悟——原来还可以通过这样。然后你会更加理解UDS(Unix Domain Socket,非TCP/IP里面的那个socket,很多人会困惑与此)的出现,此刻你心里对于Server-Client端互相建立起IPC链接的过程才将变得明朗,甚至可以推出RPC(Remote Procedure Calls)的实现模型。
到这里,你再去看Binder的实现,从宏观的模型开始,一切都变得异常清晰起来。对于Binder Client和Binder Service各自的角色有了理解,Binder驱动与ServiceManager的联动,就变得更加清楚——和UDS或者RPC是不是很类似?甚至更容易理解一些,如果更加抽象的形容,ServiceManager就像DNS一样,负责Client查询到BinderService的IP地址(这也就理解了为何ServiceManager的通信标志恒为0),而Binder驱动则是路由器的角色。
然后细化下去,针对每一个模块本身的职责,询问更细节的实现,永远记住,先有的问题,之后才有的代码——这样才能理解为何Parcel是必要的(跨进程通信的高效序列化数据载体),为何IBinder或BpBinder是必须的,AIDL又是什么用——代码实现是新鲜的,但是有了之前的铺垫和对问题的预期,它们的出现才是可理解的。这是理解Android源码之“术”。
当然,说起来容易,做起来难。
整套模块看下来,抛开信息检索能力不谈,你需要补一些C++的基础,需要补计算机系统的基础,甚至需要理解设计模式——但不是说你成为任何一方的专家才能理解,只是随着一点点深入问题,随时去补课罢了。所以说跳着看书的能力是必须的,不是你想不想或者喜不喜欢的问题,它就是必须的——你唯一的问题就是愿不愿意让自己适应它,还是找个借口绕路。
所以这个问题又回到了最初提出的观点——Android的功夫,在Android之外。你要想“理解”而非单纯的“知道”,想“学习”而非单纯的“记诵”,我觉得没有他路可走。
总结起来就是:
先理解模块对应的要解决的“问题”是什么,再去给问题找解决方案的思路去理解源码。
理解源码的功夫不止在Android本身,也要提高Android之外的姿势水平。
最后,继续鄙视那些玩了几个app、听说Android开发语言用Java就对Android嗤之以鼻的自大狂们——对于Android这个庞大的知识库来说,90%的人离入门都还差得远呢。