andorid面试题和笔记(持续更新)(framework)

##事件分发机制
首先事件指的是触摸事件,首先是viewgroup的事件分发,viewgroup里面有子view,ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。

简单的来说就是viewgroup遍历自己的子view,如果子view中有viewgroup,就继续遍历这个viewgroup的子view,都是调用的dispatchTouchEvent来分发事件,dispatchTouchEvent会返回一个布尔值类型的参数,事件会一直分发,一直在某个view调用dispatchTouchEvent返回true,表示事件分发到此结束,返回true的这个view就是需要接受这个事件的view,

ViewGroup的dispatchTouchEvent是真正在执行“分发”工作,而View的dispatchTouchEvent方法,并不执行分发工作,或者说它分发的对象就是自己,决定是否把touch事件交给自己处理,而处理的方法,便是onTouchEvent事件,这里说到了view的onTouchEvent事件是这个时候开始执行,那么viewgroup的onTouchEvent什么时候执行呢?,当所有的子view调用dispatchTouchEvent都是返回false的时候,这个时候viewgroup的onTouchEvent就会执行

事实上,一次完整的Touch事件,应该是由一个Down、一个Up和若干个Move组成的
但是dispatchTouchEvent只是分发了Down事件,只有返回true的时候,证明这个view需要 这个事件,然后在继续分发Up和Move事件给它,

ViewGroup还有个onInterceptTouchEvent,看名字便知道这是个拦截事件。这个拦截事件需要分两种情况来说明:

1.假如我们在某个ViewGroup的onInterceptTouchEvent中,将Action为Down的Touch事件返回true,那便表示将该ViewGroup的所有下发操作拦截掉,这种情况下,mTarget会一直为null,因为mTarget是在Down事件中赋值的。由于mTarge为null,该ViewGroup的onTouchEvent事件被执行。这种情况下可以把这个ViewGroup直接当成View来对待。

2.假如我们在某个ViewGroup的onInterceptTouchEvent中,将Acion为Down的Touch事件都返回false,其他的都返回True,这种情况下,Down事件能正常分发,若子View都返回false,那mTarget还是为空,无影响。若某个子View返回了true,mTarget被赋值了,在Action_Move和Aciton_UP分发到该ViewGroup时,便会给mTarget分发一个Action_Delete的MotionEvent,同时清空mTarget的值,使得接下去的Action_Move(如果上一个操作不是UP)将由ViewGroup的onTouchEvent处理。

Ontouch的优先级高于onclick,onclick的事件在ontouchevent中,只有在ontouch返回false的时候才会继续执行ontouchevent

##view的渲染机制
基础知识
CPU: 中央处理器,它集成了运算,缓冲,控制等单元,包括绘图功能.CPU将对象处理为多维图形,纹理(Bitmaps、Drawables等都是一起打包到统一的纹理).

GPU:一个类似于CPU的专门用来处理Graphics的处理器, 作用用来帮助加快格栅化操作,当然,也有相应的缓存数据(例如缓存已经光栅化过的bitmap等)机制。

OpenGL ES是手持嵌入式设备的3DAPI,跨平台的、功能完善的2D和3D图形应用程序接口API,有一套固定渲染管线流程. 附相关OpenGL渲染流程资料

DisplayList 在Android把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的。DisplayList持有所有将要交给GPU绘制到屏幕上的数据信息。

1,Android系统每隔16ms重新绘制一次activity,也就是说你的app必须在16ms内完成屏幕刷新的所有逻辑操作,这样才能达到60帧/s。而用户一般所看到的卡顿是由于Android的渲染性能造成的。

2,将复杂的UI转换成用户看得懂的图像并绘制到屏幕上是由格栅化操作完成的
格栅化将字符串,按钮,路径或者形状的一些高级对象拆分到不同的像素上在屏幕上进行显示,这是一个非常耗时的操作而手机里有一块硬件就是为了加速完成这个操作就是GPU(图像处理单元)
渲染过程

CPU在图像绘制之前向GPU输入指令这一过程通过OpenGL-ES 完成
也就是说在屏幕绘制UI对象的时候都需要在CPU中转化成多边形再传递GPU进行格栅化操作
cpu将对象转换为多边形耗时 同样上传到GPU也耗时所以我们要减少对象转换次数以及上传数据的次数,幸运的是OpenGL-ES API允许数据上传到GPU进行数据保存,当下一次绘制按钮的时候只要在GPU的存储器里引用它 所以渲染性能的优化就是尽快的上传数据到GPU尽可能长的在不修改数据的条件下保存数据

##动画原理

首先看下view的源码

  public void startAnimation(Animation animation) {
        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
        setAnimation(animation);
        invalidateParentCaches();
        invalidate(true);
    }

开始一个动画,在setAnimation之后,调用invalidate刷新自己的界面

Android 动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的,

dispatchDraw()   
{   
    ....   
    Animation a = ChildView.getAnimation()   
    Transformation tm = a.getTransformation();   
    Use tm to set ChildView's Canvas;   
    Invalidate();   
    ....   
} 

ParentView 在分发绘制的时候,获取childview的动画属性值,不断的进行Invalidate,直到childview绘制完成

##ANR原理
android设计了一种机制,认为一些阻挡它生命周期的返回,不能无限制下去。当满足超时条件,会弹框提醒用户中止或者等待操作

系统都设计了哪些ANR:
1:KeyDispatchTimeout(5 seconds) –主要类型
按键或触摸事件在特定时间内无响应
2:BroadcastTimeout(10 seconds)
BroadcastReceiver 在特定时间内无法处理完成
3:ServiceTimeout(20 seconds)
Service 在特定的时间内无法处理完成
除此之外,还有 ContentProvider,只是一般很少见。

发生场景
耗时的工作(比如数据库操作,I/O,连接网络或者别的有
可能阻碍 UI 线程的操作)把它放入单独的线程处理.
比如打开wifi(因为跨进程操作,有可能wifiserver那边处理超时)
读写文件(操作是个iowait负载较大的行为,很容易anr)
查询语句(在数据库内容暴增之后,出现严重的性能问题,产生anr)
SharedPreferences 的commit操作,本身是个等待操作,在我们activity退出时,有时保存当前状态,方便恢复,会使用commit,如果我们也有一个此时在操作,因为这个操作是有个锁,引起anr
list的排序。(算法的质量,以及当列表数目激增后,是否能快速算完,是个耗时操作,会产生anr)
bitmap的运算,(旋转,特效处理等)
ThreadPoolExecutor 线程池,当我们从这里获取一个线程时候,如果此时所有线程都被使用,就只能迫使等待,此时会出现anr

##oom是否可以try catch
oom属于错误不属于异常 不能try catch(个人观点)

##Android有多个资源文件夹,应用在不同分辨率下是如何查找对应文件夹下的资源的,描述整个过程

dpi范围密度
0dpi~120dpildpi
120dpi~160dpimdpi
160dpi~240dpihdpi
240dpi~320dpixhdpi
320dpi~480dpixxhdpi
480dpi~640dpixxxhdpi

dpi= context.getResources().getDisplayMetrics().densityDpi
根据手机不同的dpi安卓会对应加载不同的资源文件

##java四种引用
###强引用
平时使用最多的
比如下面
Object object =new Object();
String str =“hello”;
强引用有引用变量指向时永远不会被垃圾回收,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。

###软引用
如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;
如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
软引用可用来实现内存敏感的高速缓存,比如网页缓存、图片缓存等。使用软引用能防止内存泄露,增强程序的健壮性。
SoftReference的特点是它的一个实例保存对一个Java对象的软引用, 该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。
也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对 这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。
另外,一旦垃圾线程回收该Java对象之 后,get()方法将返回null。

###弱引用
 弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。
 
弱引用关联的对象只有弱引用与之关联的时候会被系统回收,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。
比如

 People people=new People("zhouqian",20);  
        WeakReference<People>reference=new WeakReference<People>(people);

WeakReference弱引用于强引用people关联,这个时候不会被系统回收

###虚引用
虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。
  要注意的是,虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

##如何保证线程安全
基本上所有的并发模式在解决线程安全问题上,都采用“序列化访问临界资源”的方案,即在同一时刻,只能有一个线程访问临界资源,也称同步互斥访问。
通常来说,是在访问临界资源的代码前面加上一个锁,当访问完临界资源后释放锁,让其他线程继续访问。
在Java中,提供了两种方式来实现同步互斥访问:synchronized和Lock。

非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。

线程安全必须要使用很多synchronized关键字来同步控制,所以必然会导致性能的降低。

所以在使用的时候,如果是多个线程操作同一个对象,那么使用线程安全的Vector;否则,就使用效率更高的ArrayList。

hashmap相关知识
hash碰撞指的是 hashmap在存储数据的时候,是依靠hash值去进行存储的,如果这个时候有俩个数据的hash值一致,就会导致hash碰撞,
当hashmap的大小不够的时候,会自动扩容,进行resize,并且重新计算hash值
hashmap的默认长度为16,是2的N次方,是因为16的2进制为1111,在与数据进行与运算时候不会破坏原来的数据结构,均匀分布。避免hash碰撞的概率

线程相关知识
创建线程的三种方式
通过Callable和Future创建线程 有返回值的线程
通过Runnable接口创建线程类 无返回值的线程
继承Thread类创建线程类

使用volatile关键字会强制将修改的值立即写入主存;
每个线程都有自己的工作内存,工作内存的值是主内存的备份,
volatile保证可见性,
使用volatile关键字可以使工作内存中的缓存无效,这样线程就会去主内存中拿值,能确保值的正确性

线程池的优势
①降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
②提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行;
③方便线程并发数的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统或oom等状况,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源使用率

newFixedThreadPool线程池
newFixedThreadPool只有核心线程,并且这些线程都不会被回收,也就是 它能够更快速的响应外界请求 。从下面的newFixedThreadPool方法的实现可以看出,newFixedThreadPool只有核心线程,并且不存在超时机制,采用LinkedBlockingQueue,所以对于任务队列的大小也是没有限制的

newCachedThreadPool
这个线程池中的最大线程数可以任意大
当线程池中的线程都处于活动状态的时候,线程池就会创建一个新的线程来处理任务。该线程池中的线程超时时长为60秒,所以当线程处于闲置状态超过60秒的时候便会被回收。

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(Permanet Generation)。老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

handlermessage所在线程和handler创建线程有关系。如果handler是在主线程创建的那么handlermessage也是在主线程,如果是子线程,那么handlermessage也是在子线程

handler loop messagequene

handler发送消息
looper.loop循环拿取messagequene队列中的消息,并且dispatchmessage分发出去
最后调用handlermessage来处理

activity启动流程

zygote进程
当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。
开启一个app就是fork一个zygote进程

Instrumentation 这个类就是完成对Application和Activity初始化和生命周期的工具类。

Launcher 是一个APP,用来启动手机上面的应用,通过AMS来通知zygote进程来fork一个新进程,来开启我们的目标App的

SystemServer也是一个进程,而且是由zygote进程fork出来的。
系统里面重要的服务都是在这个进程里面开启的,比如
ActivityManagerService、PackageManagerService、WindowManagerService

ActivityManagerService,简称AMS,服务端对象,负责管理系统中所有Activity的生命周期。

databind缺点
省去findviewbyid的步骤 -> kotlin也不需要findview
xml中自定检查空指针 -> kotlin有防空判断
需要在xml中设置默认值才能看到预览界面
由于android studio 对xml的语法检查较弱 不好进行错误定位

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binder无Android,binde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值