目录
1.分辨率与资源文件
inDensity
表示目标图片的 dpi(放在哪个资源文件夹下),inTargetDensity
表示目标屏幕的 dpi
2.View绘制
- Android View 绘制流程, View 测量原理
- Requestlayout,onlayout,onDraw,DrawChild区别与联系
- invalidate和postInvalidate的区别及使用:invalidate在主线程中调用,postInvalidate在子线程中调用,最终调的也是view.invalidate();
3.避免卡顿
1.主线程不要做耗时操作;
2.界面布局尽量简单,避免下一个 vsync 信号来的时候这一帧还没画完,造成掉帧。
4.View事件分发机制
OnTouchEvent()方法是获取的对屏幕的各种操作,比如向左向右滑动,点击返回按钮等等。属于一个宏观的屏幕触摸监控。
OnTouchListener()方法是获取某一个控件某一个View的点击监控。
onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。假如onTouch方法返回false,会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。
点击事件被拦截,但是想传到下面的View,如何操作?
使用 getParent().requestDisallowInterceptTouchEvent(true);
5.自定义View
参考:Android自定义View全解 ,
- 自定义组合控件:将多个控件组合成为一个新的控件,主要解决多次重复使用同一类型的布局;重点在子控件布局排列。
- 自定义系统控件(View的子类,如TextView):在原生控件基础上加一些定制化功能;重点是复写onDraw方法绘制特征。
- 直接继承View: 需重写onMeasure, onDraw方法;
- 继承ViewGroup:需重写onMeasure, onLayout 方法;
直接继承View时需要有几点注意:
1、在onDraw当中对padding属性进行处理。
2、在onMeasure过程中对wrap_content属性进行处理。
3、至少要有一个构造方法。
直接集成ViewGroup更复杂:要复写onMeasure, onLayout, 还需考虑事件分发问题。
如何优化自定义View:
1. 减少onDraw的调用,多使用有参的invalidate;
2. 利用GPU硬件加速,(只用来处理其擅长处理的图片);
3. 不要在onDraw方法内创建对象;
4. View也应该尽可能的保存其属性。
自定义View如何提供获取View属性的接口:自定义属性。
6.Bitmap
Bitmap对象的理解:包含java部分和C部分。Android自动回收机制只能释放java部分,要通过recycle去释放c部分。
android 3.0 到7.1 bitmap是放在dalvik heap中, 8.0 以后放在native heap中
不要在主线程处理bitmap;降低采样率;不用时调用recycle及时释放。
Bitmap如何处理大图,如一张30M的大图,如何预防OOM? 降低分辨率,缩放。
参考:Bitmap使用优化
可以用对象池缓存Bitmap,避免每次创建和销毁。
// 以下代码是一个简单的Bitmap对象池的实现
public class BitmapPool {
// 一个存储Bitmap对象的队列
private Queue<Bitmap> queue;
// 对象池的最大容量
private int capacity;
// 构造方法,初始化队列和容量
public BitmapPool(int capacity) {
this.queue = new LinkedList<>();
this.capacity = capacity;
}
// 从对象池中获取一个Bitmap对象,如果没有空闲的对象,就返回null
public Bitmap getBitmap() {
return queue.poll();
}
// 将一个Bitmap对象归还到对象池中,如果对象池已满,就回收该对象
public void returnBitmap(Bitmap bitmap) {
if (queue.size() < capacity) {
queue.offer(bitmap);
} else {
bitmap.recycle();
}
}
}
6.1.图片库
- 图片库对比:ImageLoader, Picasso,Glide,Fresco 等。Glide和picasso使用及区别
- LRUCache原理:维护了一个集合LinkedHashMap,该LinkedHashMap是以访问顺序排序的。当调用put()方法时,就会在结合中添加元素,如果满了就用LinkedHashMap的迭代器删除队首元素,即近期最少访问的元素。当调用get()方法访问缓存对象时,就会调用LinkedHashMap的get()方法获得对应集合元素,同时会更新该元素到队尾。 默认大小一般设置为运行时内存的1/8。LruCache用于内存级缓存,可基于其做三级缓存。
- 图片加载原理:通过三级缓存机制获取Bitmap对象,在draw方法中用canvas绘制出来。参考:三级缓存基本使用
- Glide内存缓存如何控制大小?
主要涉及缓存机制,生命周期管理。
缓存机制:活动缓存(CPU中的一块内存,是寄存器与外部内存之间的桥梁)、内存、磁盘。BitmapPool(复用池)防止内存抖动。
生命周期管理:可传Application、Activity, Fragment, View。与传入的对象的生命周期绑定。
7.一些重要View
RecycleView 和ListView
- RecycleView 和ListView区别,ListView并没有被废弃,参考 RecyclerView和ListView的区别 ,源码分析:
- ListView只能在垂直方向上滚动;recycleView能支持水平、网格、瀑布流方式;
- RecycleView能局部刷新,就能避免调用许多无用的bindView;容易实现添加item、删除item的动画效果。容易实现拖拽、侧滑删除等功能。
- ListView通过AdapterView.OnItemClickListener接口来探测点击事件。而RecyclerView则通过RecyclerView.OnItemTouchListener接口来探测触摸事件。它虽然增加了实现的难度,但是却给予开发人员拦截触摸事件更多的控制权限;
- ListView 可以设置选择模式,单项选择,多项选择等;
- ListView能通过addHeaderView(), addFooterView()添加头视图和尾视图。
- 列表页展示界面,需要支持动画,或者频繁更新,局部刷新,建议使用RecyclerView,更加强大完善,易扩展;其它情况(如微信卡包列表页)两者都OK,但ListView在使用上会更加方便快捷;
其他
ListView图片加载错乱的原理和解决方案: 使用了缓存convertView进行优化引起的。 解决方法:给图片设置tag,若tag正确才显示。
动画框架实现原理
调整View在ParentView中的起始坐标、旋转角度等。
状态栏
下拉状态栏不会影响activity的生命周期
其它
- AlertDialog, popupWindow, Activity区别:AlertDialog是非阻塞式对话框:AlertDialog弹出时,后台还可以做事情;而PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有当我们调用了dismiss方法的后,PopupWindow退出,程序才会向下执行。
- ViewPager使用细节,如何设置成每次只初始化当前的Fragment,其他的不初始化? 用懒加载模式,在setUserVisibleHint 中判断可见时才进行加载。
- 计算一个view的嵌套层级:递归调用view.getParent ;
- 约束布局Constraint;