最近整理了一些Android中的知识点,纯干货,偷偷告诉你,这也是面试的高频面试题哦。
1.解决 Android 多进程导致 Application 重复创建问题(process 造成多个 Application)
http://conorlee.top/2017/02/2...
onCreate 方法中判断进程的名称,只有在符合要求的进程里,才执行初始化操作;
抽象出一个与 Application 生命周期同步的类,并根据不同的进程创建相应的 Application 实例。
2.通过 Binder 传递数据的限制
减少通过intent传递的数据,将非必须字段使用transient关键字修饰
将对象转化为JSON字符串,减少数据体积
3.后台启动 Activity 失效
场景:如果我们正在玩着游戏,此时手机后台可能有个下载某 App 的任务在执行。当 App 下载完之后突然弹出安装界面,中断了游戏界面的交互,这种情况会造成用户体验极差,而最终用户的吐槽对象都会转移到 Android 手机或者 Android 系统本身。
Android10(API29)开始,对后台进程启动Activity做了一定限制,目的就是尽可能的避免当前前台用户的交互被打断,保证当前屏幕上涨势的内容不受影响。
解决方法:
Android官方建议我们使用通知来替代直接启动Activity操作。
4.Android启动activity之taskAffinity
单纯使用 taskAffinity 不能导致 Activity 被创建在新的任务栈中,需要配合 singleTask 或者 singleInstance!
taskAffinity + allowTaskReparenting
allowTaskReparenting 赋予 Activity 在各个 Task 中间转移的特性。一个在后台任务栈中的 Activity A,当有其他任务进入前台,并且 taskAffinity 与 A 相同,则会自动将 A 添加到当前启动的任务栈中
5.事件分发
dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent
步骤 1:判断当前 ViewGroup 是否需要拦截此 touch 事件,如果拦截则此次 touch 事件不再会传递给子 View
(或者以 CANCEL 的方式通知子 View)。
步骤 2:如果没有拦截,则将事件分发给子 View 继续处理,如果子 View 将此次事件捕获,
则将 mFirstTouchTarget 赋值给捕获 touch 事件的 View。
如果没有子 View 捕获处理 touch 事件,ViewGroup 会通过自身的 onTouchEvent 方法进行处理。
后续的 MOVE、UP 等事件的分发交给谁,取决于它们的起始事件 Down 是由谁捕获的。
步骤 3:根据 mFirstTouchTarget 重新分发事件。
判断是否需要拦截:主要是根据onInterceptTouchEvent方法的返回值决定是否拦截
在Down事件中将touch事件分发给子View: 如果子view捕获消费了touch事件,会对mFirstTouchTarget进行赋值
最后,Down, Move,Up事件会根据mFirstTouchTarget是否为null,决定自己处理touch事件,还是再次分发给子View
特殊点:
Down事件特殊之处: 事件的起点;决定后续事件由谁来消费处理
mFirstTouchTarget作用:记录捕获消费touch事件的view,是一个链表结构
CANCEL事件的触发场景:当父视图先不拦截,然后在MOVE事件中重新拦截,此时子View会接受到一个CANCEL事件
6.自定义View
自定义 UI 控件有 2 种方式:
继承系统提供的成熟控件(比如 LinearLayout、RelativeLayout、ImageView 等);
直接继承自系统 View 或者 ViewGroup,并自绘显示内容。
一共有 3 种测量模式。
EXACTLY:表示在 XML 布局文件中宽高使用 match_parent 或者固定大小的宽高;
AT_MOST:表示在 XML 布局文件中宽高使用 wrap_content;
UNSPECIFIED:父容器没有对当前 View 有任何限制,当前 View 可以取任意尺寸,比如 ListView 中的 item。
onDraw:主要负责绘制 UI 元素;
onMeasure:主要负责测量自定义控件具体显示的宽高;
onLayout:主要是在自定义 ViewGroup 中复写,并实现子 View 的显示位置,并在其中介绍了自定义属性的使用方法。
7.RecyclerView缓存
setLayoutManager:必选项,设置 RV 的布局管理器,决定 RV 的显示风格。常用的有线性布局管理器(LinearLayoutManager)、网格布局管理器(GridLayoutManager)、瀑布流布局管理器(StaggeredGridLayoutManager)。
setAdapter:必选项,设置 RV 的数据适配器。当数据发生改变时,以通知者的身份,通知 RV 数据改变进行列表刷新操作。
addItemDecoration:非必选项,设置 RV 中 Item 的装饰器,经常用来设置 Item 的分割线。
setItemAnimator:非必选项,设置 RV 中 Item 的动画。
RecyclerView 是如何经过测量、布局,最终绘制到屏幕上,其中大部分工作是通过委托给 LayoutManager 来实现的。
RecyclerView 的缓存复用机制,主要是通过内部类 Recycler 来实现。
RV 会将测量 onMeasure 和布局 onLayout 的工作委托给 LayoutManager 来执行,不同的 LayoutManager 会有不同风格的布局显示,这是一种策略模式
四级缓存:
(1)第一级缓存 mAttachedScrap&mChangedScrap
这两者主要用来缓存屏幕内的 ViewHolder
(2)第二级缓存 mCachedViews
它用来缓存移除屏幕之外的 ViewHolder,默认情况下缓存个数是 2,不过可以通过 setViewCacheSize 方法来改变缓存的容量大小。如果 mCachedViews 的容量已满,则会根据 FIFO 的规则将旧 ViewHolder 抛弃,然后添加新的 ViewHolder
(3)第三级缓存 ViewCacheExtension
开发人员可以通过继承 ViewCacheExtension,并复写抽象方法 getViewForPositionAndType 来实现自己的缓存机制。
(4)第四级缓存 RecycledViewPool
RecycledViewPool 同样是用来缓存屏幕外的 ViewHolder,当 mCachedViews 中的个数已满(默认为 2),则从 mCachedViews 中淘汰出来的 ViewHolder 会先缓存到 RecycledViewPool 中。ViewHolder 在被缓存到 RecycledViewPool 时,会将内部的数据清理,因此从 RecycledViewPool 中取出来的 ViewHolder 需要重新调用 onBindViewHolder 绑定数据。这就同最早的 ListView 中的使用 ViewHolder 复用 convertView 的道理是一致的,因此 RV 也算是将 ListView 的优点完美的继承过来。
RecycledViewPool 还有一个重要功能,官方对其有如下解释:
RecycledViewPool lets you share Views between multiple RecyclerViews.
可以看出,多个 RV 之间可以共享一个 RecycledViewPool,这对于多 tab 界面的优化效果会很显著。需要注意的是,RecycledViewPool 是根据 type 来获取 ViewHolder,每个 type 默认最大缓存 5 个。因此多个 RecyclerView 共享 RecycledViewPool 时,必须确保共享的 RecyclerView 使用的 Adapter 是同一个,或 view type 是不会冲突的。
好了,今天和大家分享这些,后续会持续更新,欢迎关注。