部分面试题地址**<br /> [https://github.com/Kingwentao/Awesome-Android-Interview](https://github.com/Kingwentao/Awesome-Android-Interview)<br />** 1. Binder的工作机制**<br />1. 直观来说,Binder是Android中的一个类,它继承了IBinder接口 <br />2. 从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在linux中没有 <br />3. 从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁 <br />4. 从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务<br />为什么使用在Android上<br />性能方面 <br />在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。<br />安全方面 <br />传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。
2. Binder与AIDL的关系
Binder是一个类,它实现了IBinder接口,而IBinder接口定义了与远程对象的交互协议。通常在进行跨进程通信时,不需要实现IBinder接口,直接从Binder派生即可。
除了实现IBinder接口外,Binder中还提供了两个重要的接口。
(1)Transact(),客户端调用,用于发送调用请求
(2)onTransact(),服务端响应,用于接收调用请求
Binder成为了客户端与服务端的通信媒介,其主要用在Service组件应用中。
Service与客户端通信,有两种方式,AIDL和Messenger。AIDL基于Binder,而Messenger基于AIDL
3.自定义View流程
Android自定义view,View的绘制流程是从viewRoot的perfromTraversal方法开始,主要三个方法:
onMeasure() 测量宽高
onLayout() 确定view在父容器上的摆布位置
onDraw() 是将view绘制到屏幕上的
4.View事件分发
~public boolean dispatchTouchEvent(MotionEvent event)
返回true表示事件被消费,本次的事件终止。
返回false表示View以及子View均没有消费事件,将调用父View的onTouchEvent方法
~public boolean onInterceptTouchEvent(MotionEvent ev) —viewGroup特有方法
返回true表示拦截了事件,那么事件将不再向下分发而是调用View本身的onTouchEvent方法。
返回false表示不做拦截,事件将向下分发到子View的dispatchTouchEvent方法。
~public boolean onTouchEvent(MotionEvent ev)
真正对MotionEvent进行处理或者说消费的方法。
返回true表示事件被消费,本次的事件终止。
返回false表示事件没有被消费,将调用父View的onTouchEvent方法
三点需要特别强调一下
1.子View可以通过requestDisallowInterceptTouchEvent方法干预父View的事件分发过程(ACTION_DOWN事件除外),而这就是我们处理滑动冲突常用的关键方法。
2.如果设置了onTouchListener,其里的onTouch方法返回true,则onTouchEvent方法不会被调用,所以三者优先级是onTouch->onTouchEvent->onClick(onClick 在onTouchEvent中)
3.View 的onTouchEvent 方法默认都会消费掉事件(返回true),除非它是不可点击的(clickable和longClickable同时为false),View的longClickable默认为false,clickable需要区分情况,如Button的clickable默认为true,而TextView的clickable默认为false。
参考:https://blog.csdn.net/u010302764/article/details/72636459
AsyncTask的工作原理
AsyncTask是Android提供的轻量级的异步类。AsyncTask的实现原理 = 线程池 + Handler,采用了线程池,每个线程的操作都是顺序的。有任务调度和任务队列**
简介:参考:https://www.jianshu.com/p/37502bbbb25a
AsyncTask 核心 & 常用的方法如下:
调用方式:
总结:某些情况下不用AsyncTask原因:多任务情况下需要创建多个AsyncTask并执行execute(),而且是都是顺序的。执行多个异步任务必须创建一个AsyncTask。且AsyncTask顺序执行,必须得等上一个任务完成后才进入下一个任务。
2.AIDL 跨进程通讯
简介:AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信( IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
作用:Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
AIDL创建过程:
(1)在工程的src下,新建立一个文本文件,将要实现的函数放在这个文件中,后缀为.aidl。
(2)刷新工程后,就会发现在gen包下,有一个同名的java文件,这是aidl工具自动生成的,里面,就有我们要实现的函数。
(3)Aidl定义好后,我们就要实现我们的remote service了。它也是继承自service的。
(4)Service实现后,要将它在mainfest.xml设置为remote.注意,客户端服务端在同个App中,android:process=”:remote”,代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process=”remote”,没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。
(5)最后,来实现我们的客户端,也就是Activity,来调用service。
总结:
Broadcast、Aidl、ContentProvider、Messager的区别和适用场景
Broadcast:发送和接收广播,可实现消息的传递
Aidl:全称Android Interface definition language顾名思义,就是不同进程间的通信接口
ContentProvider:暴露app的数据访问接口,让其他应该访问app数据
Messager:本质是Aidl,对Aidl进行了封装,不用写.aidl文件
各自的优缺点
Broadcast:只要注册了广播,都能收到,有点范围广,缺点速度慢必须在一定时间完成处理操作(onRecevice执行必须在10秒完成,否则系统认为该程序无响应造成ANR,所以不能做耗时的操作)
Aidl:进程间的通信,速度快(系统底层直接是共享内存),性能稳,效率高,一般进程间通信就用它。
Messager:效率应该是和Aidl是一样的,与Aidl的区别在于Messager是线程安全的,而Aidl是非线程安全的,所以Aidl在使用的时候应该注意这个问题
ContentProvider:一般是成熟的App暴露自己的数据,其他app可以获取到数据,数据本身不是实时的,而前面三种是实时的数据
Messager和Aidl的比较
1. Messenger本质也是AIDL,只是进行了封装,开发的时候不用再写.aidl文件。
结合我自身的使用,因为不用去写.aidl文件,相比起来,Messenger使用起来十分简单。前面也说了,Messenger本质上也是AIDL,故在底层进程间通信这一块,两者的效率应该是一样的。
2. 在service端,Messenger处理client端的请求是单线程的,而AIDL是多线程的。
使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。
3. client的方法,使用AIDL获取返回值是同步的,而Messenger是异步的。
Messenger只提供了一个方法进行进程间通信,就是send(Message msg)方法,发送的是一个Message,没有返回值,要拿到返回值,需要把client的Messenger作为msg.replyTo参数传递过去,service端处理完之后,在调用客户端的Messenger的send(Message msg)方法把返回值传递回client,这个过程是异步的,而AIDL你可以自己指定方法,指定返回值,它获取返回值是同步的。
其实,第二点是有办法解决的,在service端,Messenger的Handler可以只当作一个转发器,不处理请求,只转发请求到相应的处理线程(多是相应的HandlerThread),这样也可以达到异步的效果。