如果我是Android面试官九

一、Android事件分发机制

1、MotionEvent事件

MotionEvent事件主要有以下三种类型,ACTION_DOWN、ACTION_MOVE、ACTION_UP。也就是手指按下屏幕,移动,再抬起。

2、事件分发的三个重要方法

MotionEvent事件最终是要发送到一个具体的View上去执行。而最终要在哪个View去执行,是由View的三个方法共同来决定的。

1)public boolean dispatchTouchEvent

此方法用于事件分发,返回值如果是true表示事件被消费,无论是被当前View消费还是其子View消费,都会返回true,事件被终止。如果返回false则表明没有被消费,会触发父控件的touchEvent事件。

2)public boolean onInterceptTouchEvent

此方法用于事件拦截。当ViewGroup接收到一个MotionEvent事件时,会先调用此方法,判断是否需要拦截。返回值表示事件是否需要拦截。如果为true,表示需要拦截,事件不会继续向下分发,会调用当前控件的touchEvent方法。返回false,表示事件不被拦截会继续向下分发,调用子布局的dispatchTouchEvent方法。注意,此方法只有ViewGroup有,View没有。

3)public boolean onTouchEvent

此方法用于消费事件。返回值表示事件是否被消费,返回true表示事件被消费,本次事件终止。返回false表示事件未被消费,会调用父控件的onTouchEvent方法。

3、点击事件产生顺序

Activity->Window->顶级View->分发到子View

我们看到,从根级Group会一直想子View分发,途中如果事件被拦截,则停止分发调用当前touchEvent事件。如果一直没有拦截,则会分发到最顶层子View。子View如果没有消费会调用父布局的touchEvent事件。如果全程都没有消费,最终会调用Activity的onTouchEvent方法结束。

4、点击事件优先级

如果设置了View的onTouchListener事件,onTouchListener中的onTouch方法会被回调。onTouch方法返回true,则onTouchEvent方法不会被调用。onClick方法是在onTouchEvent中。三者优先级为onTouch->onTouchEvent->onClick

5、注事事项

View的onTouchEvent方法默认会消费掉事件,返回true。

二、Android多线程的实现

1、Thread

线程是比进程更小的执行单元,每个进程有多个线程,线程是由程序负责控制,而进程则是由系统负责控制。

线程的五个状态,新建状态、就绪状态、运行状态、阻塞状态、终止状态。

线程的三种创建方式。

1)继承Thread类。

2)实现Runnable接口。

3)使用匿名方法类。

2、HandlerThread

HandlerThread是一个继承自Thread的类。除了与Thread相同的功能之外,HandlerThread还持有一个Looper对象。这个Looper对象可以用于创建一个handler。这样handler就可以运行在别的线程了。通过HandlerThread可以实现在子线程中的消息分发和处理。

3、AsyncTask

AsyncTask可以在后台开启一个线程执行任务,当任务执行完成后,可以在UI线程更新。使用AsyncTask时通常需要重写以下几个方法。onPreExecute、doInBackground、onPostExecute和onProgressUpdate。

AsyncTask的原理是线程池+Handler机制。

AsyncTask的线程池的数量是和CPU核心数相关的,而线程池的队列是阻塞式,并且上限为128。这就意味着AsyncTask不适合做一些长期在后台运行的,大数据量的任务。除了doInBackground方法外的几个常用方法都是通过handler机制调用的。

4、IntentService

IntentService是Service的子类,拥有Service全部生命周期,并且拥有全部特性。在onCreate被执行时,内部会开启一个线程,用于执行耗时操作。

IntentService内部创建的线程是HandlerThread,在onStart方法中会创建message,并把消息发送到子线程的消息队列中。消息被处理时会调用onHandleIntent方法,这也是我们要实现的方法。在所有任务都完成后,会调用stopSelf来销毁自身。

IntentService省去了我们创建Thread的过程,并且会新建一个线程,多任务按顺序执行,并且执行过程中不能取消该任务。

5、RxJava
RxJava主要功能就是异步。其子线程与主线程之间的便利切换能够为我们提供很好的异步操作处理。然而RxJava所带来的方便不止于此,还有很多强大的操作符可以优化我们的代码。

三、ActivityThread工作原理

ActivityThread的main方法主要功能是绑定应用进程到ActivityServiceManager中并且启动主线程Handler用于UI线程消息处理。

1)main方法通过thread.attach方法绑定应用进程。

2)初始化Looper。

四、嵌套滑动实现原理

所谓嵌套滑动,就是NestedScrolling机制。主要包含NestedScrollingParent和NestedScrollingChild两个类。

外部控件实现NestedScrollingParent接口,其内部View滑动时会把dx和dy参数传入到父类控件中。父类控件可以选择对其进行消耗,并将剩余部分返换给View。

关于协作,如果你想实现与NestedScrollingParent协作的内部View,记得实现NestedScrollingChild,然后借助NestedScrollingChildHelper这个辅助类即可。

原理就是滑动时候如ACTION_DOWN等动作会调用parent中的方法,然后处理完又会调用其它回调方法。最终实现协作联动。

五、View绘制原理、自定义View与ViewGroup

绘制原理分为三大方法onMeasure、onLayout以及onDraw。

measure时注意MeasureSpec这个组合尺寸,高2位代表SpecMode。低30位表示大小数值。

在自定义View时,注意onDraw方法中,我们通过Paint类和Canvas类可以实现图形与文字的绘制,可以设置其颜色等参数,还有重叠效果之类。还可以在canvas中通过paint绘制各种内容。

自定义ViewGroup中,需要设置LayoutParams。之后通过重写onMeasure、onLayout等方法可以实现我们想要的布局摆放效果。

六、View、SurfaceView和TextureView

后两者是专门用于视频展示的。不与主View冲突。

七、主线程Looper.loop为什么不会造成死循环

简单地说,当没有消息时,主线程looper会处于阻塞状态,当有新的消息来临时,会唤醒线程,继续处理任务。

这里附上鸿阳大神分享的Android学习路线 Android学习路线

 

 

你可能感兴趣的:(android基础巩固)