Android基础(16 - 30)
目录
16,自定义View如何考虑机型适配(重要);
17,Handler机制(重要);
18,ListView中图片错位的原理和解决方法(重要);
19,ApplicationContext和ActivityContext的区别(重要);
20,Service与Activity之间通信的几种方式;
21,LinearLayout和RelativeLayout性能对比(重要);
22,优化自定义view(重要);
23,了解ContentProvider(重要);
24,数组和链表的区别;
25,如何安全的退出一个已经开启多个activity的APP?
26,Android系统的有哪些安全机制?
27,Asset目录与res目录的区别;
28,Binder机制;
29,分块加载巨图;
30,广播分为几种方式?
16,自定义View如何考虑机型适配(重要):
- 合理使用warp_content,match_parent;
- 尽可能的是使用RelativeLayout;
- 针对不同的机型,使用不同的布局文件放在对应的目录下,android会自动匹配;
- 尽量使用点9图片;
- 使用与密度无关的像素单位dp,sp;
- 引入android的百分比布局;
- 切图的时候切大分辨率的图,应用到布局当中。在小分辨率的手机上也会有很好的显示效果;
17,Handler机制(重要):
Handler包括四个角色:
- Handler:负责发送消息处理消息。
- Message:消息实体对象,handler通过sendMessage将实体放到消息队列中。
- MessageQueQue:存放消息的队列。
- Looper:消息轮询器,不停的从消息队列中取出消息交给handler处理。
在主线程创建Handler,在需要发送消息的地方创建一个Message,通过handler发送。这个消息回到MessageQueQue中,然后Looper会将这个消息取出交给handler处理。
Handler可以有多个,但是在同一线程中Looper和MessageQueQue只能有一个。
18,ListView中图片错位的原理和解决方法(重要):
错位分析:
-
如果我们只是简单的显示数据,没有convertView的复用和异步操作,就不会产生图片错位。
-
重用convertView但没有异步操作也不会有错位现象。
-
例如我们的listView中刚好显示7个item,当向下滑动时,显示出item8,而item8是重用的item1,如果此时异步网络请求item8的图片,比item1的图片慢,那么item8就会显示item1的图片。当item8下载完成,此时用户向上滑显示item1时,又复用的item8的image。这样就导致的图片错位。
解决方法:
对imageview设置tag,并预设一张图片,向下滑动后,item8显示,item1隐藏。但由于item1是第一次进来就显示,所以一般情况下,item1都会比item8先下载完,此时可见的item8的tag和隐藏了的item1的url不匹配,所以就算item1的图片下载完也不会显示到item8中,因为tag标识的永远是可见图片中的url。
19,ApplicationContext和ActivityContext的区别(重要):
这是两种不同的context,也是最常见的两种。
- 第一种中context的生命周期与Application的生命周期相关的,context随着Application的销毁而销毁,伴随application的一生,与activity的生命周期无关。
- 第二种中的context跟Activity的生命周期是相关的,但是对一个Application来说,Activity可以销毁几次,那么属于Activity的context就会销毁多次。
至于用哪种context,得看应用场景,个人感觉用Activity的context好一点,不过也有的时候必须使用Application的context.application context。
20,Service与Activity之间通信的几种方式:
- 通过Binder对象;
- 通过broadcast(广播)的形式;
21,LinearLayout和RelativeLayout性能对比(重要):
-
RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure;
-
RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
-
在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。
22,优化自定义view(重要):
-
为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。
-
你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate().因此请尽量减少调用invaildate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate会强制重绘整个view。
-
另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。
-
如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。
PS:【转发】自定义的ViewGroup
ViewGroup是容器,用来包含其他控件,而View是真正意义上看得见摸得着的,它需要将自己画出来。ViewGroup需要重写onMeasure方法测量子控件的宽高和自己的宽高,然后实现onLayout方法摆放子控件。而 View则是需要重写onMeasure根据测量模式和父控件给出的建议的宽高值计算自己的宽高,然后再父控件为其指定的区域绘制自己的图形。
23,了解ContentProvider(重要):
【转发】
ContentProvider初探
24,数组和链表的区别:
数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。
25,如何安全的退出一个已经开启多个activity的APP?
在Application中持有一个全局的集合(List),进而在其onCreate()方法添加到这个集合,最终遍历所有的activcity并finish。
ActivityCompat.finishAffinity(this);
26,Android系统的有哪些安全机制?
应用程序签名机制,权限申明机制,访问控制机制,进程通讯机制,内存管理机制。
27,Asset目录与res目录的区别:
区别【转发】
Asset目录与res目录的区别
28,Binder机制:
Binder是Android的系统进程通许方式之一简称IPC;
Binder使用Clinet->Server通讯方式,Binder框架定义的四个角色,Server,Client,ServiceManager,以及Binder驱动,其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间,Binder驱动程序提供Dev/binder与用户空间交互,Server,Client,ServiceManager,通过open和ioctl文件操作函数和Binder交互。
【转发】
Binder原理
29,分块加载巨图:
图片分块加载
图片的分块加载在地图绘制的情况上最为明显,当想获取一张尺寸很大的图片的某一小块区域时,就用到了图片的分块加载,在Android中BitmapRegionDecoder类的功能就是加载一张图片的指定区域。BitmapRegionDecoder类的使用非常简单,API很少并且一目了然,如下:
// 创建实例
mDecoder = BitmapRegionDecoder.newInstance(mFile.getAbsolutePath(), false);
// 获取原图片宽高
mDecoder.getWidth();
mDecoder.getHeight();
// 加载(10, 10) - (80, 80) 区域内原始精度的Bitmap对象
Rect rect = new Rect(10, 10, 80, 80);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bitmap = mDecoder.decodeRegion(rect, options);
// 回收释放Native层内存
mDecoder.recycle();
30,广播分为几种方式?
- 什么是安卓的Broadcast?
安卓的四大组件之一,是一种广泛应用在应用程序之间传输信息的机制。
三种方式:
-
普通广播 (Normal broadcast)
- 所有监听该广播接受者都可以监听到该广播
- 同级别接收先后顺序是随机的(无序)
- 级别低的后收到广播
- 接收器不能截断广播的继续传播,也不能处理广播
- 同级别动态注册高于静态注册
-
有序广播 (Oredered broadcast)
- 按照接收者的优先顺序来接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大优先级越高,可以终止广播的继续传播,接受者可以修改intent的内容。
- 同级别接收顺序是随机的
- 级别低的后收到
- 能截断广播的继续传播,高级别的广播接收器接收广播后能决定时候截断。
- 能处理广播
- 同级别动态注册高于静态注册
-
异步广播 (粘滞性滞留广播 Sticky broadcast) ps:已被弃用
- 不能处理结果给下一个接收者,无法终止广播。
- 一直存在
- 可以先发送广播,再注册接收器
- 需要在清单文件添加android.permission.BROADCAST_STICKY权限
-
注意!!!!
- BroadReceiver生命周期只有十秒左右,不能直接执行耗时操作,不然会出现ANR(应用程序无响应),也不能用子线程来做,因为每次广播来的时候都会创建一个Reveiver对象,并且调用onReceiver,执行完之后 ,对象会立刻被销毁,子线程也没了 。
- 要做耗时操作的话,应该通过发送Intent给Service,由Service来完成。
- 动态注册广播接受者的话要在Destory回调事件进行unregister。
【转发】
Broadcast 三种广播的使用总结