2020年Android应届生秋招技术面试题补充(飞猪、阿里云、小米、有赞)

1.如何定义心跳包的间隔时间

并不是一个固定的值,需要根据网络环境来选择,网络状态好的时候可以定为30s一次,当网络状态不好的时候,断线比较频繁的时候就可以定为5s一次

2.view的事件分发机制https://www.jianshu.com/p/7d50a6b0b6af

本质上是对motionEvent的传递,motionEvent的传递顺序如下:Activity、winow、decorview、viewgroup、view,在viewgroup中有三个非常重要的函数,分别是
dispatchtouchEvent:进行事件的分发;
oninterceptTouchEvent:拦截事件;
onTouchEvent:消耗事件;
dispatchTouchEvent受到当前viewgroup的intercepttouchEvent和下一级的dispathtouchEvent的影响
oninterceptTouchEvent会拦截motionEvent事件,在同一个事件序列中只会调用一次,只有viewgroup中有此事件
onTouchEvent:消耗事件,在dispathtouchEvent中调用,如果当前view不消耗此事件,则在后续的同一事件序列中此view都无法再次接收事件
onTouchListener、onTouchEvent都会在dispathTouchEvent中调用,但是onTouchListenr的优先级高于onTouchEvent,onClickListener在onTouchEvent中调用,如果在onTouchListenre中的onTouch返回true,则后续的两个方法都不会被调用
子view和通过requestDisallowInterceptTouchEvent来干预父元素除了Action_Down以外的事件的分发

3.Error和Exception的区别https://blog.csdn.net/weixin_42124070/article/details/80833629

Error和Exception都是throwable的子类,exception是可预期异常,是可以捕获这种异常,并进行相应的异常处理,
Error是不可预期的异常,当出现这种异常的时候,会直接导致jvm不可处理或不可恢复,这种异常是不可捕获的,如OOM,NoClassDfFoundError,在exception中又分为检查性异常和非检查性异常,检查性异常就是在编译之前,编译器会指出哪里有异常,需要使用try-catch捕获,如IoException,非检查性异常就是在编译前不会提示,在运行时可能会出现的异常,如ArrayIndexOfBoundsException(数组下标越界)

4.什么情况下会造成内存泄漏https://blog.csdn.net/u011479990/article/details/78480091

bitmap使用过大的图片,
bitmap不再使用时,没有调用recycle释放资源
使用static修饰context,使用static修饰时,context的生命周期就属于这个类,而不是实例
io流资源得不到释放,
adapte的converview创建的过多,没有复用

5.synchronized放在静态方法和非静态方法有什么区别

synchronzied修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”;
synchronized修饰静态方法的时候,其实是类锁,因为是静态方法,它吧整个类锁起来了,
1⃣️.同一个对象在两个线程中分别访问该对象的两个非静态同步方法
会产生互斥,对于非静态对象来说,锁针对的是调用方法的对象,其他同步需要等到上一个同步方法调用完毕,释放对象锁以后,才会调用下一个同步方法,
2⃣️.不同对象在两个线程中调用同一个非静态同步方法
不会产生互斥,非静态同步方法上锁针对的是调用者,但是当前有两个对象,且在不同的线程中。A对象调用a方法不影响B对象调用b方法。
3⃣️.用类直接在两个线程中调用两个不同的静态同步方法
会产生互斥,对于静态方法来说,锁上的是当前的类,即被调用者所属的类,当调用了该类其中的一个静态同步方法以后,该类就已经上锁了,必须要等到持有这个类的锁的对象释放掉才能调用其他的方法。
4⃣️.用一个类的静态对象在两个线程中调用静态方法或非静态方法
会产生互斥,因为在调用静态同步方法是,该类会被上锁,其他的对象需要等到锁被释放了才可以继续调用。
5⃣️.一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法
不会产生互斥,因为产生的锁不同,调用静态同步方法锁的是类,调用非静态方法锁的是调用对象

6.apk打包步骤

1)Android Asset Packaging Tool工具,会打包资源文件,并生产对应的R.java文件和resources.arsc文件。
2)AIDL会将.aidl文件编译成.java文件
3)JAVAC工具将R.java、AIDL接口生成的java文件、应用代码文件编译为一个个class文件。
4)dx脚本将这些class文件打包为一个dex文件
5)apkbuilder脚本将资源文件、dex文件生成未签名的.apk文件
6)jar-signer对apk签名

7.gradle编译步骤https://www.jianshu.com/p/d983de9891ad

aapt错误,找不到对应资源

8.handler、loop各部分作用,postDelay延时事件插入的原理

handler中有三部分,handler消息处理者,messageQueue消息链表,Looper消息泵,
在主线程中会自动创建handler,handler会自动绑定一个loop
直接实现Handler.CallBack接口可以简化代码,避免创建一个匿名 内部类
handler通过sendmessage发送消息到messageQueue中,messageQueue的enqueueMessage按照消息的处理的时间先后顺序进行排序,looper去轮询消息链表,将要到时处理的消息通过dispathMessage方法发送给接收的handler否则柱塞到指定时间,handler调用handlerMessage方法来处理消息,处理完后,looper回收此消息

9.Android内存管理机制

每次新建一个app进程的时候,系统都会给这个进程分配一个够用的内存,当分配的内存被消耗完后,系统会再次给这个进程分配一点进程,但是这个进程所消耗的内存是有个上限值的,当超过这个上限会,系统就会认为这个进程发生了OutOfMemory,每个app都运行在一个独立的虚拟机中,互不影响,当某个app出现OOM的时候,系统就kill掉这个进程而不影响其他app的运行,系统会优先保证前台进程的运行,只有当出现内存不足的时候,才会杀死一些不可见的进程,进程的优先级如下:前台进程>可见进程>服务进程>后台进程>空进程

10.mvp、mvc、mvvm的优缺点

MVC:
优点:1.吧业务逻辑都分配到controller,模块化层度高,变更业务时只需要更换controller
缺点:1.controller测试困难,因为controll需要view来驱动,
2.view无法组件化,view是强依赖于module的
MVP:
优点:1.便于测试,P层与view都是通过接口来交互的
2.view可以组件化
缺点:P层中还有View->Model、Model->View的同步逻辑,比较笨拙,维护困难
MVVM:
优点:1.可维护性高,解决了MVP中view和model的同步问题,提供了双向绑定
2.简化测试
缺点:1.不适用于过于简单的页面
2.对于大型应用,状态图过多,viewmodel的构建和维护成本过高
3.数据显示生命在xml布局文件中,无法DeBug

11.各种排序的原理、稳定性、时间复杂度、空间复杂度

插冒归稳,堆快归log2(n)
选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
插入排序:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
希尔排序:是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序
归并排序:采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
快速排序:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
堆排序:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

12.TCP和UDP的区别,TCP如何保证数据的传输

Tcp面向连接,点对点的传输,交付可靠
UDP面向无连接,不保证交付

13.Zxing的优化https://www.jianshu.com/p/9bd4e5d8a405

1.支持格式:Zxing支持很多种扫描格式,我只需要支持二维码即可,所以在启动扫码界面的时候可以传入一个QRCODE,如果不传入参数,则会默认支持所有格式
2.聚焦时间:在AutoFocusManager中,设置缩短聚焦时间
3.扫描精度:原来的扫描区域在方框中,需要完全对准了才能扫描到,在CameraManger改为采用全幅图像
4.结果处理:原来的是在扫描界面绘制一个bitmap,改为返回数据到上一个界面
5.图片拉伸:修改支持的分辨率

14.四大组件

activity、service、BroadcastReceiver、ContentProvider

15.自定义view步骤https://blog.csdn.net/jim1451/article/details/79915308

1.在value文件下创建attrs.xml文件,添加需要对view支持的属性
2.创建类文件,添加构造题,获得属性并初始化属性
3.重写onMeasure,测量view,确定view的尺寸来支持wrap_content属性
4.重写onDraw,在view上绘制

16.synchronized和volatile的了解,何为原子性、可见性,a++是原子性的吗https://zhidao.baidu.com/question/1639502478823598620.html

volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.
volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.
volatile可以保证可见性、顺序性,synchroized可以保证可见性、原子性
可见性:在一个线程中对某个变量的修改可以让其他线程立即知道;
原子性:多个操作要么全部执行,要不全部不执行;
顺序性:jvm会将代码进行优化,在不影响程序正常运行的情况下将指令打乱重新排序;

17.强引用,弱引用,软引用,虚引用的区别及其引用场景
https://blog.csdn.net/a568418299/article/details/78914637

强引用:使用new关键词创建,在垃圾回收期间不会对其进行回收,即使内存不足,也不会回收,而是抛出oom,除非清除栈中对其的引用
软引用:非必须引用,在内存即将溢出的时候会对齐进行回收,内存不足时get返回为null
弱引用:在第二次进行垃圾回收是,无论内存情况如何都会进行回收,get有可能返回为null
虚引用:只要垃圾回收机制开始工作就会被回收,isEnQueued 主要用于检查对象是否已经从内存中释放

18.binder机制,Android中有哪些进程间通信的方式https://www.jianshu.com/p/f3feb05e3281

Binder基于C/S架构,有三大成员,client、services、servicesmanager,每个service都会在servicemanager上注册自己的服务,当client需要使用service的服务时,会通过binder在servicemanager上查询是否有对应的服务,binder会返回查询的服务,然后client会生成一个服务的的代理类,来间接的调用service的方法,当client使用service的服务的时候,会吧参数直接发送给binder,binder再把请求方法和参数发送给对应的service,此时的client会柱塞,当service处理完以后,会将结果返回给binder,binder在去唤醒client来接收services处理完后返回的结果
其他跨进程通信的方式还有socket、service(AIDL)、文件共享、ContentProvider、Broadcast

19.说一下垃圾回收算法,为何要分新生代和老年代

垃圾对象判断:
引用计数算法:被引用一次+1,引用实习-1,当为0时jvm认定为垃圾对象,但是无法解决环形引用
可达性分析算法:从GCROOT为起始节点向下搜索,存在的即为可用对象,不存在与引用链中的为垃圾对象,GCROOT可为栈中引用的对象、方法区中的类静态属性引用的对象、方法区中的常量引用的对象、本地方法栈中 JNI(Native 方法)的引用对象、
垃圾回收算法:
标记清除算法:扫描所有对象将存活的标记,将未标记的对象进行清除,会产生内存碎片
标记复制算法:扫描所有对象将存活的标记,将标记对象复制到另一块内存空间中,清空原来的内存空间
标记整理算法:标记整理实际上是在标记清除算法上的优化,执行完标记清除全过程之后,再一次对内存进行整理,将所有存活对象统一向一端移动,这样解决了内存碎片问题
分代回收算法:年轻代以复制算法为主,老年代以标记整理算法为主。原因是年轻代对象比较多,每次垃圾回收都有很多的垃圾对象回收,而且要尽可能快的减少生命周期短的对象,存活的对象较少,这时候复制算法比较适合,只要将有标记的对象复制到另一个内存区域,其余全部清除,并且复制的数量较少,效率较高;而老年代是年轻代筛选出来的对象,被标记比较高,需要删除的对象比较少,显然采用标记整理效率较高

20.http和https的区别

https基于SSL、TSL加密协议(非对称加密、公钥私钥),密文传输,默认端口未443,http明文传输、80端口

21.activity的启动模式https://blog.csdn.net/zy_jibai/article/details/80587083

standard默认模式:启动的activity会按照顺序依次被压入task中
singleTop栈顶复用:启动activity之前会判断栈定是否已有其实例,没有的话会新建一个实例并压入栈顶,否则不新建,执行onNewIntent方法
singleTask栈内复用:启动activity之前会判断栈里是否已有其实例,没有的话会新建一个实例并压入栈顶,否则不新建,执行onNewIntent方法
singleIncetense单实例模式:每次启动activity,会按照清单文件中分配的task来新建,每个栈中只能有一个实例,如果已经创建,则会激活之前创建的

22.final、finally、finalizehttps://www.cnblogs.com/smart-hwt/p/8257330.html

final表示变量不可修改、方法不可重写、类不可继承
finally表示在try-catch中无论如何最后都会执行,如果在try或者catch中有return语句,那么会在执行return之前执行finally语句,
finalize是Object的方法,在GC的时候会调用,可以在其中执行一些资源回收,如关闭文件

23.Android 6.0、8.0新特性

6.0:新的权限模式,运行时权限;移除对Apache Http Client的支持,改用HttpURLConnection
8.0不允许http明文传输

25.recycleview的回收复用

RecycleView滑动场景下回收复用涉及到的两个结构体
mCacheViews:优先级最高,回收时,最新的viewholder都是往mCacheViews里放,如果满了则将旧的viewHoler移到RecycleViewPool中,当复用时。先在mCacheViews中找,并且只有原来位置的viewHolder才能用,也就是需要postion相等才能复用,如果在mCacheViews中没有才会去RecycleViewPool中找,在mCacheViews中的viewHolder在复用时不需要重新绑定,mCacheViews的默认大小为2
ViewPool(RecycleViewPool):优先级低于mCacheViews,在viewpool中的viewholder和新的一样,只要type一样,就可以拿出来复用,只需要重新绑定一下数据
viewpool的默认大小为5

26.Glide的缓存策略

Glide.with(this).load(URL).into(控件的实例)
Glide的缓存机制:
1.Resource缓存:首先Resource缓存就是缓存整体的图片资源,当首次使用的时候从网络将图片下载下来以后,缓存到本地,如果需要再次使用这个图片的时候,就 不用通过网络下载,直接在本地读取即可,它使用的三级缓存策略如下:
一级缓存:内存中缓存被GC回收的资源,使用LRU(最近最少使用算法),当需要再次使用被回收的资源的时候,直接从内存中读取
二级缓存:使用弱引用缓存正在使用的资源到一个集合中保存,当系统执行GC的时候,会回收没有强引用的资源
三级缓存:磁盘缓存,网络下载成功,将图片缓存到本地
2.Bitmap缓存:
图片压缩:使用RGB_565格式,每个像素点只有2bit;
Bitmap缓存算法:使用BitmapPool来缓存Bitmap,使用的也是LRU算法,当需要使用Bitmap的时候,先从Bitmap的池子中获取,如果找不到合适的Bitmap,再去创建,再使用完毕后,不是直接调用Bitmap.recycle()释放内存,而是将其放入缓存池
Bitmap是以键值对的形式来缓存的,吧bitmap的参数,如长宽高id来作为key值,当需要使用bitmap的时候,直接根据对应的长宽高来寻找

27.Retrofit的基本流程

Retrofit主要是在create方法中采用动态代理模式实现接口方法,这个过程构建了一个ServiceMethod对象,根据方法注解获取请求方法,参数类型和参数注解拼接请求的连接,当一切都准备好了以后会吧数据添加到Retrofit的RequestBuilder中,然后当我们主动发起网络请求的时候会调用okHttp发起网络请求,okHttp的配置包括参数和URL等在RequestBuilder的build方法中实现,并发起真正的网络请求
使用的设计模式:建造者模式(Retrofit.Builder的创建)、适配器模式(rxjava中使用callAdapter和convertAdapter来进行适配)、代理模式(代理请求的接口类)等等

28.如何设计一个图片加载模块

缓存、懒加载
主要思路,假设A界面需要一次性加载20张图,每张100k,那么在界面初始化的时候就会消耗2000k的内存或者流量,而且很耗时,如果使用懒加载,在界面初始化的时候,只显示看的到的图片,假设能看到4张,那么在初始化的时候就只需要加载4张到内存中,界面打开的速度会提升,剩下的地方先显示占位图,可以在界面初始化完成后在讲其他的图片渲染完,图片保存的方式采用缓存的方式,分别为网络、内存、文件,在加载图片的时候首先到内存中找,如果没有再去数据库中找,如果还是没有就通过网络下载,然后吧小的图片,使用次数高的存在内存中,其他的存入数据库中。

29.RxJava基本知识

1.将链式编程风格和异步结合在一起
2.使用观察者模式
3.基本使用:创建被观察者(Observable);创建观察者(Observer);建立订阅关系(subscribe)
4.常用操作符:
merge:将多个Observable合并为一个,照时间线来连接,merge一遇到异常将停止发射数据,发送onError通知。
map:对上游发送的每一个事件应用一个函数, 使得每一个事件都按照指定的函数去变化
flatmap:将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里.且不保证顺序
concatmap:在flatmap的基础上保证顺序
RxJava1.0和RxJava2.0的区别

30.view的绘制流程

measure:判断是否需要重新计算View的大小;
layout:判断是否需要重新计算View的位置;
draw:判断是否需要重新绘制View;
通过WindowManager将DecorView传入ViewRootImpl,在ViewRootImpl中的performTraversals()方法中分别对View进行measure, layout, draw,通过ViewGroup的类分别对子View依次进行测量,摆放和绘制。

31.死锁的条件和避免

1.互斥;任意一个资源在同一时刻只能有一个线程占用;不能破坏
2.请求和保持;一个线程因请求新的资源而柱塞时,对已获得的资源不释放;一次性申请所有资源
3.不剥夺;线程已获得的资源在使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才能释放资源;占用部分资源的线程在进一步申请其他资源时,如果申请不到,可以释放占有的资源
4.环形等待;若干个线程之间形成一种头尾相接的循环等待资源;靠按序申请资源来预防,按某一顺序申请资源,释放资源则反序释放。

32.dp、dpi、px的关系

px:手机上的像素点,如:1920X1080 就表示在高度上有1920个像素,在宽度上有1080个像素
dpi:每英寸像素
dp:安卓中的相对大小
inch:屏幕大小,英寸,
dpi = px / inch
dp = dpi * 160

33.AsyncTask的基本原理和与Handler的区别

AsyncTask相对于Handle,代码较为简单,使用更便捷,也可以准确控制子线程、底层为一个线程池和Handler
AsyncTask<Params, Progress, Result>
三个参数分别是启动任务执行的输入参数、后台任务执行的进度、后台计算结果的类型
doInBackground(Params…) 后台执行
onPostExecute(Result) 相当于Handler 处理UI的方式
onProgressUpdate(Progress…)此方法在主线程执行,用于显示任务执行的进度
onPreExecute()这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled() 用户调用取消时,要做的操作
AsyncTask在执行任务的时候会在内部创建一个静态final线程池来管理要运行的任务,也就是说当你调用execute后,Asynctask会把任务交给线程池,由线程池来管理创建Thread和运行Thread,串行的执行任务,然后对UI的操作就交给来handler,

34.ThreadLocal和ThreadPool

ThreadLocal作用:保证各个线程的数据互不干扰,使用set方法来保存数据,使用get方法取值内部有一个ThreadLocalMap来保存值;
ThreadPool作用:减少重复创建和销毁线程带来的内存损耗

35.TCP如何保证数据可靠性

1.应用数据被分割成 TCP 认为最适合发送的数据块
2.TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层
3.校验和,检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
4.TCP的接收端会丢弃重复的数据
5.当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。
6.当网络拥塞时,减少数据的发送
7.停止等待协议,每发完一个分组就- 停止发送,等待对方确认。在收到确认后再发下一个分组
8.超时重传,当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

36.ANR出现的情况及其解决办法

在Activity(5s)、BroadcastReceiver(10s)、Service(20s)执行耗时操作会出现ANR
执行耗时操作的时候最好在子线程执行,如果需要刷新UI,则可以使用、AsyncTask

猜你喜欢

转载自blog.csdn.net/qq_17282141/article/details/101069445