Android知识小结
这是一个知识的总结,所以没有详解的讲解。
一.分辨率
Android中dp长度、sp字体使用、px像素、in英寸、pt英寸1/72、mm毫米
了解dp首先要知道density,density是一个抽象的单位,density值表示每英寸有多少个显示点,与分辨率是两个概念
QVGA屏density=120 QVGA(240*320)
HVGA屏density=160 HVGA(320*480)
WVGA屏density=240 WVGA(480*800)
WQVGA屏density=120 WQVGA(240*400)
在说转换系数,转换系数就是两个不同屏幕density的比例。例如:WVGA屏转QVGA屏,就是120/240。有了这个转换系数就能在不同的屏显示不的长度了。
屏幕一般可分为,状态栏,标题栏和控制区域。
当屏幕density=240时,使用hdpi 标签的资源
当屏幕density=160时,使用mdpi标签的资源
当屏幕density=120时,使用ldpi标签的资源
当屏幕density=320时,使用xhdpi标签的资源
当屏幕density=480时,使用xxhdpi标签的资源
二.Touch事件机制
1.ViewGoup 有三个事件 onTouchEvent事件处理 dispatchTouchEvent事件分发 onInterceptTouchEvent事件拦截
2.view 有两个事件 onTouchEvent事件处理 dispatchTouchEvent事件分发
3.最顶层的viewGoup把事件分发到最底层的view,最底层的view通过返回值,告诉父类的view是否消耗到这个事件
4.事实上Touch事件值响应ACTION_DOWN事件(返回true的view才是真正消耗MotionEvent事件,才会响应ACTION_UP和ACTION_MOVE)
其他的事件分发原理是一样的
当我们理解了这个事件分发的机制就能解决很多问题了。
1.为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?
滑动菜单的功能是通过给ListView注册了一个touch事件来实现的。如果你在onTouch方法里处理完了滑动逻辑后返回true,那么ListView本身的滚动事件就被屏蔽了,自然也就无法滑动(原理同前面例子中按钮不能点击),因此解决办法就是在onTouch方法里返回false。
2.为什么图片轮播器里的图片使用Button而不用ImageView?
图片轮播器里使用Button,主要就是因为Button是可点击的,而ImageView是不可点击的。如果想要使用ImageView,可以有两种改法。第一,在ImageView的onTouch方法里返回true,这样可以保证ACTION_DOWN之后的其它action都能得到执行,才能实现图片滚动的效果。第二,在布局文件里面给ImageView增加一个android:clickable="true"的属性,这样ImageView变成可点击的之后,即使在onTouch里返回了false,ACTION_DOWN之后的其它action也是可以得到执行的。
三.view的绘制过程
view的绘制分三步走,onMeasure,onLayout,onDraw view的绘制首先要计算大小,然后布局坐标,最后就绘制。
1.onMeasure计算大小,有两个参数,分别是widthMeasureSpec,heightMeasureSpec这两个参数。每一个MeasureSpec有一个尺寸(s ize)和一个模式(mode)构成,所以要对widthMeasureSpec和heightMeasureSpec做拆分。view的大小通过父类和它自己共同控制的
Mode一共有三种
EXACTLY 父类决定子类的大小
AT_MOST 父类限定子类的最大尺寸
UNSPECIFIED 父类不对子类做限制,子类需要多大就多大
2.onMeasure计算完之后,就开始布局onLayout,onLayout会返回坐标,这样就能在指定的地方绘制了,onLayout在ViewGroup使用。可以控制子view。
3.onDraw就是绘制了,会返回一个画布,想画啥就画啥了。
了解了view的绘制过程,就可以通过重写控件或者自定义控件,实现各种的需求。
四.Handler, Looper的理解
首先理解四个概念
Looper:不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper中的prepare方法,通过这个方法就可以在线程上创建一个Looper,如果多个Looper会抛异常。UI线程默认就有一个Looper。使用Handler的send方法就可以往消息队列放一条msg,Looper.loop()这个方法就是消息循环,有一个while循环不断去消息队列MessageQueue获取msg。通过回调Handler的dispatchMessage,dispatchMessage会给handleCallback或者handleMessage。这样就实现了线程间的通讯。
如果要详细理解,百度一下就有十分多的资料。
五.Android跨进程通讯
1.广播和Content Provider ,此处略。
2.aidl
aidl的使用,一个进程作为服务端,一个程序作为客户端。他们之间的通讯通过Service。服务端提供调用的接口,客户端绑定服务,调用服务端的方法。aidl支持普通的数据类型,其他数据类型要序列化,继承Parcelable。
3.共享UserId
android的安全机制来自于lunix,同时通过userid权限来管理的,例如root,system和普通的权限。后来也出了个SEAndroid。只要你共享了userid,不同应用之间就能通讯了。共享userid必须签名是一致。