转载自:http://blog.csdn.net/amurocrash/article/details/48714607
首先向各位严重推荐主席这本书《Android开发艺术探索》。
再感谢主席邀请写这篇读书笔记 + 书评。书已经完整的翻完一遍了,但是还没有细致的品读并run代码,最近有时间正好系统的把整本书从内容到代码都梳理一遍,一方面方便自己总结,一方面也为主席宣传,如果你还在犹豫要不要入手这本书的时候,希望看完我的笔记,能激发你购买的动力。OK,言归正传,下面先简单写几句书评,本人技术有限,只是从自身角度出发做一些分享,大神请轻喷。
在你已经厌倦只会做功能+xml堆界面,在你想要了解Android更多的技术细节,在你渴望自己在Android开发上获得一次涅槃的时候,主席的这本书应运而生了。通读完本书,第一感觉这本书没有华丽的辞藻,没有酷炫的卖弄,没有生涩的技术词汇堆砌,有的,只是玉刚童鞋对于技术的执著和热爱,对于分享的热忱和真挚。可以说,这就是一本技术人员的书,因为我们热爱的只是技术而已。全书结构清晰,脉络整齐,我个人认为分为以下几个大类:Activity机制,View机制,iPC机制,必须知道的Android核心技术,必须知道的Android优化技术。可以说,这本书是在你熟悉使用api之后进阶的第一选择,因为优秀的程序员绝对不是api的搬运工,我们更需要了解优秀的api背后的设计理念和底层机制,只有知道这些,我们才能真正做到融汇贯通,举一反三,从用api成长到写api。
这个blog我准备分四到五篇来写,主要还是记录阅读过程中遇到的重难点和tips,也可以看作是提纲挈领,查漏补缺吧。我希望看主席的书如果会有一些模模糊糊的地方,我这几篇tips能帮助到你,以上。
今天第一篇主要是前两章+remoteView,加remoteView的原因主要是这货本质也就是个aidl实现的IPC,就放在一起了,大家发现任何问题也可以在评论中给出,感谢。
Android开发艺术探索Tips
Chapter-1 Activity的生命周期和启动模式
----------------------------
1.新Activity是透明主题时,旧Activity不会走onStop;
2.Activity切换时,旧Activity的onPause会先执行,然后才会启动新的Activity;
3.Activity在异常情况下被回收时,onSaveInstanceState方法会被回调,回调时机是在onStop之前,当Activity被重新创建的时 候,onRestoreInstanceState方法会被回调,时序在onStart之后;
4.Activity的LaunchMode
a. standard 系统默认。每次启动会重新创建新的实例,谁启动了这个Activity,这个Activity就在谁的栈里。
b. singleTop 栈顶复用模式。该Activity的onNewIntent方法会被回调,onCreate和onStart并不会被调用。
c. singleTask 栈内复用模式。只要该Activity在一个栈中存在,都不会重新创建,onNewIntent会被回调。如果不存在,系统会先寻找是否存在需要的栈,如果不存在该栈,就创建一个任务栈,然后把这个Activity放进去;如果存在,就会创建到已经存在的这个栈中。
d. singleInstance。具有此种模式的Activity只能单独存在于一个任务栈。
5.标识Activity任务栈名称的属性:TaskAffinity,默认为应用包名。
6.IntentFilter匹配规则。
a. action匹配规则:要求intent中的action 存在 且 必须和过滤规则中的其中一个相同 区分大小写;
b. category匹配规则:系统会默认加上一个android.intent.category.DEAFAULT,所以intent中可以不存在category,但如果存在就必须匹配其中一个;
c. data匹配规则:data由两部分组成,mimeType和URI,要求和action相似。如果没有指定URI,URI但默认值为content和file(schema)
Chapter-2 IPC机制
---------------
1.使用android:process会带来的问题:
静态成员和单例模式完全失效;
SharedPreferences可靠性下降;
Application会多次创建;
2.Binder的工作机制:(Page55)
3.Android中的IPC方式
a. Bundle
b. 文件共享(不建议使用系统的SharedPreferences)
c. Messenger(轻量级IPC,底层依然是AIDL)工作原理(Page70 & 代码)
d. AIDL
aa. AIDL支持的数据类型:基本数据类型;String和CharSequence;List只支持ArrayList,里面每个元素都必须被AIDL支持;Map只支持HashMap,里面每个元素都必须被AIDL支持(包括key和value);Parcelable;AIDL接口本身;
bb. 服务端可以使用CopyOnWriteArrayList和ConcurrentHashMap来进行自动线程同步,客户端拿到的依然是ArrayList和HashMap;
cc. 服务端和客户端之间做监听器,服务端需要使用RemoteCallbackList,否则客户端的监听器无法收到通知(因为服务端实质还是一份新的序列化后的监听器实例,并不是客户端那份);
dd. 客户端调用远程服务方法时,因为远程方法运行在服务端的binder线程池中,同时客户端线程会被挂起,所以如果该方法过于耗时,而客户端又是UI线程,会导致ANR,所以当确认该远程方法是耗时操作时,应避免客户端在UI线程中调用该方法。同理,当服务器调用客户端的listener方法时,该方法也运行在客户端的binder线程池中,所以如果该方法也是耗时操作,请确认运行在服务端的非UI线程中。另外,因为客户端的回调listener运行在binder线程池中,所以更新UI需要用到handler。
ee. 客户端通过IBinder.DeathRecipient来监听Binder死亡,也可以在onServiceDisconnected中监听并重连服务端。区别在于前者是在binder线程池中,访问UI需要用Handler,后者则是UI线程。
ff. 可通过自定义权限在onBind或者onTransact中进行权限验证。
e. ContentProvider(有的手机上会出现不加uses-permission依然可以访问BookProvider的问题,已和主席确认)f. Socket 一般用于网络通信,AIDL用这种方式会过于繁琐,不建议。
4.Binder连接池,通过BinderPool的方式将Binder的控制与Service本身解耦,同时只需要维护一份Service即可。这里用到了CountDownLatch,大概解释下用意:线程在await后等待,直到CountDownLatch的计数为0,BinderPool里使用它的目的是为了保证Activity获取BinderPool的时候Service已确定bind完成~
Chapter-5 RemoteViews
---------------------
1.Notification。Notification的自定义View只能使用setTextViewText, setImageViewResource, setOnClickPendingIntent等固定方法来设置View,不能像操作普通View的方式来操作。
2.AppWidgetProvider
a.本质是一个广播,配置步骤:定义界面xml,定义配置信息xml,定义实现类(继承AppWidgetProvider),AndroidManifest中声明。
b.重要回调:onEnable,第一次被添加时调用,只有一次;onUpdate,添加或更新时回调;onDelete,每次删除时回调;onDisable,最后一次删除时回调;onReceive,接收广播的action。
3.PendingIntent
a. 典型的使用场景就是和RemoteViews的点击事件配合使用;
b. 支持三种待定Intent:Activity,Service和Broadcast
c. PendingIntent相同的定义:内部的Intent和requestCode都相同。Intent相同的定义:两个Intent的componentName和intent-filter相同(不包括extras)
d. flag定义:FLAG_NO_CREATE,基本不使用;FLAG_ONE_SHOT,以第一个为准,后续的会全部和第一条保持一致,任意一条被触发,其他的都cancel;FLAG_CANCEL_CURRENT,前面的相同的PendingIntent都会被cancel,只有最新的可用;FLAG_UDPATE_CURRENT,前面的PendingIntent都会被更新(它们Intent中的extras都会被更新)
4.RemoteViews的内部机制
a. 支持的View类型:Layout:FrameLayout, LinearLayout, RelativeLayout, GridLayout; View: AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView, ViewFlipper, ListView, GridView, StackView, AdapterViewFlipper, ViewStub。
b. 简单归纳,客户端的remoteViews通过action对象,由binder机制来更新服务端的remoteViews,所以RemoteViews本身也实现了Parcelable接口(参考图Page233)
c. RemoteViews中真正操作View的方法apply和reapply,前者会加载布局并更新界面,后者则只更新界面。
5.跨进程的RemoteViews传递,模拟通知栏的实现。注意不同应用间RemoteViews的id不同,需要约定名称然后重新通过Resource.getIdentifier来获取。