Android高级岗面试刷题02

1.MVC,MVP架构的区别。

https://www.jianshu.com/p/78e0a508b1c6

结合自己项目使用的MVP谈谈感想。

2.如何解决Handler导致的内存泄漏。

Android高级岗面试刷题02_第1张图片

在java中非静态内部类和匿名内部类都会隐式持有当前类的外部引用,由于Handler是非静态内部类所以其持有当前Activity的隐式引用,如果Handler没有被释放,其所持有的外部引用也就是Activity也不可能被释放,当一个对象不需要再使用了,本来该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏。最终也就造成了OOM.......

解决办法:设置为静态内部类,并且持有Activity的弱引用。

3.LruCache算法的原理。

LRULeast Recently Used的缩写,意思也就是近期最少使用算法。LruCacheLinkedHashMap的顺序设置为LRU顺序来实现LRU缓存,每次调用get并获取到值(也就是从内存缓存中命中),则将该对象移到链表的尾端。调用put插入新的对象也是存储在链表尾端,这样当内存缓存达到设定的最大值时,将链表头部的对象(近期最少用到的)移除。

4.简述View的绘制流程。(非常重要,面试必说,不问自己也要说!)

https://www.cnblogs.com/mingfeng002/p/9143831.html

https://baijiahao.baidu.com/s?id=1652990190210449929&wfr=spider&for=pc

mWindow = new PhoneWindow(this);

mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),

mToken, mComponent.flattenToString(),

WindowManageraddView的过程,WindowManager是个接口,它的实现类是WindowManagerImpl类,而WindowManagerImpl又把相关逻辑交给了WindowManagerGlobal处理。WindowManagerGlobal是个单例类,它在进程中只存在一个实例,是它内部的addView方法最终创建了我们的核心类ViewRootImpl

可以看到这里的WindowManagerImpl 的主要功能都是通过WindowManagerGlobal来实现的

ViewRootImpl之中的requestLayout()

performTraversals()!而它里的实现就是调用咱们熟悉的performLayout()、performMeasure()、performDraw()的地方了~

1、mesarue()过程
主要作用:为整个 View 树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:
mMeasureWidth),每个 View 的控件的实际宽高都是由父视图和本身视图决定的。
具体的调用链如下: ViewRoot 根对象的属性 mView(其类型一般为 ViewGroup 类型)调用 measure()方法去
计算 View 树的大小,回调 View/ViewGroup 对象的 onMeasure()方法,该方法实现的功能如下:
1、设置本 View 视图的最终大小,该功能的实现通过调用 setMeasuredDimension()方法去设置实际
的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth)。
2 、如果该 View 对象是个 ViewGroup 类型,需要重写该 onMeasure()方法,对其子视图进行遍历的
measure() 过 程 。 对 每 个 子 视 图 的 measure() 过 程 , 是 通 过 调 用 父 类 ViewGroup.java 类 里 的
measureChildWithMargins()方法去实现,该方法内部只是简单地调用了 View 对象的 measure()方法。
2、layout 布局过程
主要作用:为将整个根据子视图的大小以及布局参数将 View 树放到合适的位置上。
具体的调用链如下:
1、layout 方法会设置该 View 视图位于父视图的坐标轴,即 mLeft,mTop,mLeft,mBottom(调用
setFrame()函数去实现)接下来回调 onLayout()方法(如果该 View 是 ViewGroup 对象,需要实现该方法,对每个子视
图进行布局)。
2、如果该 View 是个 ViewGroup 类型,需要遍历每个子视图 chiildView,调用该子视图的 layout()方法
去设置它的坐标值。
3、draw()绘图过程
由 ViewRoot 对象的 performTraversals()方法调用 draw()方法发起绘制该 View 树,值得注意的是每次发起绘
图时,并不会重新绘制每个 View 树的视图,而只会重新绘制那些“需要重绘”的视图,View 类内部变量包含了一个
标志位 DRAWN,当该视图需要重绘时,就会为该 View 添加该标志位。
调用流程 :
1 、绘制该 View 的背景
2 、为显示渐变框做一些准备操作(大多数情况下,不需要改渐变框)
3、调用 onDraw()方法绘制视图本身(每个 View 都需要重载该方法,ViewGroup 不需要实现该方法)
4、调用 dispatchDraw ()方法绘制子视图(如果该 View 类型不为 ViewGroup,即不包含子视图,不
需要重载该方法)
值得说明的是,ViewGroup 类已经为我们重写了 dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,
但可以重载父类函数实现具体的功能。
 

 

你可能感兴趣的:(Android高级岗面试实战)