读书笔记-《Android开发艺术探索》

《Android开发艺术探索》作者:任玉刚


第一章 Activity的生命周期和启动模式

  1. activity跳转的时候,如果新activity采用了透明主题,那么当前activity不会回调onStop()

  2. onSaveInstanceState()调用在onStop()之前,onRestoreInstanceState()调用在onCreate()之后

  3. 一个进程脱离四大组件而独自运行在后台中,很容易被系统杀死(从侧面也理解出,与用户无交互的功能应放在service,而不是单例中)

  4. singleTask的匹配模式为:先找符合的任务栈TaskAffinity,再找相同的实例,另外,要启动的activity为singleTask,如果某栈中存在该实例,就会把该栈整个移动到前台栈中,比如: 前台栈存在AB实例,后台栈存在CD实例, 现在启动D,那么就会变成前台栈为CD,后台栈为AB,书中图示如下:

    singleTask.png

需要注意的是,TaskAffinityallowTaskReparenting结合使用的时候,情况会比较复杂,这里引用书中原话:

当一个应用A启动了应用B的某个Activity后,如何这个Activity的allowTaskReparenting属性为true的话,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中

(ps: TaskAffinity默认为应用包名)

  1. intentFilter的匹配规则
    action : intent中的action只要有一个和过滤规则中的任何一个action相同即可匹配成功
    category : intent中可以没有category,直接匹配成功,但是如果Intent中存在category那么每一个都要和过滤规则中匹配上才成功
    data : 匹配规则与action类似
    注意隐式调用中,android默认会加上android.intent.categiry.DEFAULT,所以匹配的activity的Intent-filter中必须增加该category

第二章 IPC机制

  1. Android应用内开启多进程模式只有一种方法,就是给四大组件在AndroidManifest中指定android:process属性

  2. Parceable主要用于内存中序列化,对于磁盘存储以及网络传输建议使用Serializable

  3. 所有可以在Binder中传输的接口都需要继承IInterface接口

  4. binderDied() 和 onServiceDisconnected()区别???
    onServiceDisconnected在客户端的UI线程中被回调,而binderDied在客户端的Binder线程池中被回调,两者同样可以用于重连服务的场景

  5. transact和onTransact的区别???

  6. 跨进程通信的方法:aidl,socket,contenprovider,文件共享,intent附加extrax信息(bundle),messager

  7. aidl中,客服端调用远程服务的方法,被调用的方法运行在服务端的Binder线程池中,相反服务端调客户端也一样

  8. aidl中,接口的注册和解注册使用RemoteCallbackList实现

  9. 绑定binder的权限验证方式:permission,packageName

  10. 多service的情况,可以使用binder连接池处理

第三章 View的事件体系

  1. getX()getY(): 返回相对于当前View左上角的x和y坐标
    getRaw()YgetRawY() :返回相对于手机屏幕左上角的x和y坐标

  2. TouchSlop为系统所能识别的最小滑动距离,即小于这个数值的距离不认为为滑动,获取方式:ViewConfiguration.get(getContext()).getScaledTouchSlop()

  3. mScrollX/mScrollY指的是view的边缘和view内容边缘的滑动距离,这个通过下面图来理解就好

    mScrollX和mScrollY的变换规律示意.png

  4. requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外

  5. 触摸事件分发机制图

事件分发.png

第四章 View的工作原理

  1. measureSpec不是唯一由LayoutParams决定的,LayoutParams需要和父容器一起才能决定View的MeasureSpec,从而进一步决定View的A宽/高

  2. view最终的大小是在layout阶段确定的(参考第五点)

  3. 一个比较好的习惯是在onLayout方法中去获取View的测量宽/高或者最终宽/高

  4. 获取view测量的宽/高方法
    Activity/View#onWinndowFocusChanged
    view.post(runnable)
    VieTreeObserver

  5. getMeasuredWidth和getWidth的区别?
    getMeasuredWidth:是测量时赋值
    getWidth:是布局时赋值(右上角左边减去左上角左边)
    getMeasuredWidthgetWidth不一定相等

  6. view有一个特殊的方法setWillNotDraw,该方法是用于对于没有绘制的view进行优化的,如果明确知道一个viewgroup需要调用onDraw的时候,需要显示的关闭这个标记位

7 自定义view须知

让View支持wrap_content
如果有必要,让你的View支持padding
尽量不要在View中使用Handler,除非必要情况
View中如果有线程/动画,需要及时停止,参考View#onDeteachedFromWindow
View带有滑动嵌套情形时,需要处理好滑动冲突

第五章 理解RemoteViews

  1. PendingIntent的匹配规则:如果两个PendingIntent它们内部的Intent相同并且requestCode也相同,那么这两个PendingIntent就是相同的,其中Intent的匹配规则是ComponentName和intent-filter都相同,排除Extras

第六章 Android的Drawable

  1. 一般来说drawable是没有大小概念的,但他可以设置固有宽/高,并通过getIntrinsicWidthgetIntrinsicHeight这两个方法获取

第七章 Android动画深入分析

  1. View动画中的shareInterpoliator属性表示: 动画集合是否共享一个插值器

  2. activity的切换效果可以在startActivity(intent)/finish()之后调用overridePendingTransition(int enterAnim,int exitAnim)

  3. 使用动画的过程中建议开启硬件加速,这样会提高动画的流畅性

扩展:
补间动画的实现原理:
1.调用view的startAnimation会执行invalidate(true),然后就会遍历整个树图,然后找到viewrootimpl,接着执行它的performTraversals,这个就在正常view绘制的三大流程入口
2.其中在view绘制的时候调用的是draw(三个参数),里面执行applyLegacyAnimation,该方法最终会执行到子类的applyTransformation方法,就是具体的矩阵变换算法中,另外还会返回一个动画是否结束的标志,如果没有结束则重新走invalidate()继续绘制视图
3.applyTransformation实际操作的对象是canvas,而不是view中的具体属性值,所以补间动画不会改变view的真正大小和位置,只是对他的canvas做矩阵变换

第八章 理解Window和WindowManager

  1. window有三种类型:
    应用window: 层级为1~99
    子window:层级为1000~1999
    系统wind: 层级为2000~2999

  2. window进行添加view,更新view,删除view的操作实际是通过windowManager实现的,而windownManager又委托给WindowManagerGlobal来进行,golbal主要分如下几步来实现:
    检查参数是否合法,如果是子window那么还需要调整一些布局参数
    创建viewrootimpl并将view添加到列表中(其内部有 mViews,mRoots,mParams等集合,分别为所有window对应的view,所有window对应的viewrootimpl,所有window的布局参数)
    最后通过viewrootimpl来更新界面并完成window的添加,其实际是通过WindowSession访问WindowManagerService进行window的添加

  3. window添加流程时序图


    image.png

第九章 四大组件的工作工程

看得云里雾里

第十章 Android的消息机制

  1. ActivityThread也就是UI线程,在创建的时候就会初始化Looper,这也是在主线程中默认可以使用Handler的原因

  2. ThreadLocal是一个线程内部的数据存储类,不同线程中的数据相互独立互不干扰

  3. handler处理消息机制主要是: handler向Messagequeue插入了一条消息,Messagequeue的next方法会返回这条消息给looper,looper收到消息后就开始处理,最后又交回给handler处理,即handler的dispatchMessage方法会被调用

第十一章 Android的线程和线程池

1.ThreadPoolExecutor构造方法的参数意义:
corePoolSize : 最大核心线程数,一直存活,但是如果设置了allowCoreThreadTimeOut为true,会有超时策略
maximumPoolSize :线程池所能容纳的最大线程数
keepAliveTime: 非核心线程闲置时的超时时长,allowCoreThreadTimeOut为true时,核心线程数也会被回收
unit:超时时间单位
workQueue : 任务队列大小
threadFactor:线程共创,为线程池提供创建新线程的功能

  1. 常用四类线程池
    FixedThreadPool : 快速响应外界的请求
    CacgedTgreadPool:适合执行大量的耗时较少的任务
    ScheduledThreadPool: 主要用于执行定时任务和具有固定周期的重复任务
    SingleThreadExecutor:确保所有的任务都在同一个线程中按顺序执行

  2. AsyncTask实际是封装了Thread和Handler,IntentService实际是封装了HandlerThread和Handler

第十二章 Bitmap的加载和Cache

  1. 采用BitmapFactory.Onptions来高效加载Bitmap,其中涉及的参数:
    inJustDecodeBounds : 设为true时,BitmapFactory只会解析图片的原始宽/高信息,并不会真正地加载图片,所以这个操作是轻量级的,通常用于需要修改inSampleSize(采样率)的使用
    inSampleSize : 采样率,小于1无效,尽量使用2的指数,bitmap的像素/内存占用缩放比例为 1/(inSampleSize的2次方)

你可能感兴趣的:(读书笔记-《Android开发艺术探索》)