Android面试可能会遇到的知识点,自我救赎002

164 阅读16分钟

35岁的大龄程序员,在年底失业了,毫无人道,还是被裁的,还没有给我大礼包,黑心的狠。这几天一直在想怎么能开启一个第二职业呢,不用受主业的影响?有没有支招的,可以指导一下。

继续救赎道路:

1,线程有哪些状态?

  • 新建,可运行,运行,阻塞,死亡,等待

2,四大引用,场景举例?

  • 根据级别高低依次是:强引用,软引用,弱引用,虚引用
  • 加载大图时可以使用软引用,避免OOM
  • Handler内存泄露使用弱引用

3,软引用和弱引用的区别?

  • 区别在于:只具有弱引用的对象拥有更短暂的生命周期。
  • 在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存
  • 软引用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存

4,Activity的生命周期?

  • onCreate() -> onStart() -> onResume() -> onRestart() ->
  • onPause() -> onStop() -> onDestory()

5,Fragment的生命周期?

  • onAttach():Fragment和Activity相关联时调用
  • onCreate():Fragment被创建
  • onCreateView():创建Fragment的布局
  • onActivityCreated():当Activity完成onCreate()时调用
  • onStart():当Fragment可见时调用
  • onResume():当Fragment可见且可交互时调用
  • onPause():当Fragment不可交互但可见时调用
  • onStop():当Fragment不可见时调用
  • onDestoryView():当Fragment的UI从视图中移除时调用
  • onDestory():销毁Fragment时调用
  • onDetach():当Fragment和Activity解除关联时调用

6,Activity,Window,View三者的关系?

  • Activity是View的宿主,负责控制和管理View的展示和交互
  • Window则是View的继承者和管理者,负责协调View的渲染和事件传递

7,内存泄露相关问题?

  • 内存泄露是指应用程序中存在一些对象或者资源无法被垃圾回收器回收,导致内存占用不断增加,最终导致设备性能下降。
  • 1,对象未被正确回收:当对象的引用仍然存在时,但不再需要该对象时,没有及时释放对象会导致内存泄露
  • 2,匿名类和内部类的引用:由于匿名类和内部类会隐式持有外部类的引用,处理不好的话,可能导致外部类无法被正确回收
  • 3,单例模式:使用单例模式的对象无法被释放或者及时清理,会导致该对象一直存在内存中
  • 4,Handler:使用Handler时,未正确处理消息队列和外部类弱引用,可能导致外部类无法被回收
  • 5,长时间运行的后台任务
  • 6,Context的错误引用:当将一个长生命周期的对象与Context关联时,如果未正确解除引用,将导致Context无法被回收
  • 7,使用缓存导致的内存泄露:如果在缓存中保持过长时间的对象引用,有可能导致内存泄露
  • 8,未关闭的资源:如数据库连接,文件输入输出流,本地资源使用等,如果在使用完毕后未显示关闭这些资源,会导致内存泄露

8,如何避免内存泄露?

  • 及时释放对象:在不再使用对象时,及时将其引用置空,以便垃圾回收器能够正确回收对象
  • 使用弱引用:对于可能导致内存泄露的对象引用,使用弱引用来避免强引用导致的无法回收问题
  • 避免使用静态对象:静态对象生命周期长,容易导致内存泄露,尽量避免过度使用静态对象
  • 避免使用匿名类和内部类:匿名类和内部类隐式的持有外部类的引用,容易导致外部类无法被回收
  • 避免使用单例模式:如果单例模式对象无法及时释放,会一直存在于内存中,增加内存占用
  • 避免Handler导致的内存泄露:使用静态内部类和外部类的弱引用来避免内存泄露

9,WebView怎么避免内存泄露?

  • 避免在xml布局文件中直接嵌套WebView控件,而是采用addView的方式 new 一个WebView并加载到布局中,上下文变量使用applicationContext
  • 当Activity生命周期结束时及时销毁释放资源
  • 手动删除引用
  • 独立出一个进程
  • 让onDetachedFromWindow先走,再主动调用onDestory()之前,把WebView从它的Parent上面移除掉

10,用过哪些设计模式?

  • 单例模式,建造者模式,工厂模式,观察者模式,适配器模式

11,介绍一下观察者模式?

  • 观察者模式:它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己

12,介绍一下双亲委托模式?

  • 双亲委托就是如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
  • 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器
  • 如果父类加载器可以完成类加载任务,就返回成功,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载

13,代理模式和装饰模式的区别?

  • 代理模式:
  • 1,注重控制对方法的访问,代理者可以决定是否调用被代理对象的方法
  • 2,应在构造方法中实例化被代理的对象,不应让访问者知道,你代理了哪个对象
  • 装饰模式:
  • 1,注重为方法添加额外的行为,装饰者一定会调用被装饰对象的方法
  • 2,可以动态指定被装饰的对象,具体做法是,装饰者应该包含一个以被装饰者对象为参数的构造函数

14,策略模式和状态模式的区别?

  • 目的不同:策略模式关注的是算法的选择和使用,用于根据不同的策略执行不同的行为;而状态模式关注的是对象内部状态的变化,用于根据不同的状态执行不同的行为
  • 职责不同:策略模式将不同的算法封装成独立的策略类,客户端主动选择使用哪种策略;而状态模式将不同的状态封装成独立的状态类,并由环境类根据当前状态执行相应行为
  • 关注点不同:策略模式关注的是行为的选择和灵活性,用于状态切换算法;而状态模式关注的是状态的变化和可维护性,用于根据状态执行相应的行为

15,Boolean和AtomicBoolean的区别?

  • Boolean作为一个基本类型,主要用于表示布尔值
  • AtomicBoolean是一个线程安全的包装类,提供了原子操作和更丰富的操作方法,适用于多线程环境下的布尔值操作

16,Service的生命周期?

  • onCreate(),onStartCommand(),onBind(),onUnBind(),onDestory()
  • onStartCommand必须要实现

17,Service是哪个线程?怎么通信?

  • 主线程,使用Binder对象通信
  • 1,创建一个自定义Binder对象,继承Binder类,该Binder类必须封装一些接口,使得Client获取到该Binder类对象时可以调用,从而实现与Service的通信
  • 2,在Service中,创建一个该Binder类的实例
  • 3,重写Service的onBind()方法,返回该实例
  • 4,在Client中,调用bindService()方法,在方法中传入ServiceConnection对象,在该ServiceConnection的onServiceConnected回调方法中获取传入的Binder实例
  • 5,通过该实例调用第一步中封装的接口,实现与Service通信

18,用过哪些排序算法?

  • 冒泡排序,选择排序,插入排序
  • 冒泡排序原理:
  • 1,比较相邻的元素,如果第一个比第二个大,就交换它们两个
  • 2,对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,在这一点,最后的元素应该会是最大的数
  • 3,针对所有的元素重复以上的步骤,除了最后一个
  • 4,持续每次对越来越少的元素重复上面步骤,直到没有任何一对数字需要比较。
  • 选择排序原理:
  • 1,首先在未排序序列中找到最小元素,存放到排序序列的起始位置
  • 2,再从剩余未排序序列中继续寻找最小元素,然后放到已排序序列的末尾
  • 3,重复第二步,直到所有元素均排序完毕。
  • 插入排序原理:
  • 1,从第一个元素开始,该元素可以认为已经被排序
  • 2,取出下一个元素,在已经排序的元素序列中从后往前扫描
  • 3,如果该元素大于新元素,将该元素移到下一个位置
  • 4,重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  • 5,将新元素插入到该位置后
  • 6,重复步骤2-5

19,介绍一下贪心算法?

  • 贪心算法是指对于问题求解时总是能做出在当前看来是最好的选择,也就是说,不是从整体最优上加以考虑
  • 算法过程:
  • 1,将求解的问题分为若干个子问题
  • 2,将每一个问题求解,得到子问题的局部最优解
  • 3,将子问题的局部最优解合成原来解问题的一个解

20,介绍一下快排原理?

  • 快排原理是通过一趟排序将待排序的序列分割为左右两个子序列,左边的子序列中所有数据都比右边子序列中的数据小,然后对左右两个子序列继续进行排序,直到整个序列有序

21,浏览器输入一个地址,按下回车,这个过程是什么样的?

  • 主要会有四个步骤:
  • URL解析和DNS解析,建立TCP连接,发送HTTP请求以及接收服务器响应和页面渲染

22,简单介绍一下TCP?

  • TCP是一种面向连接的,可靠的,基于字节流的传输层通信协议

23,TCP的三次握手?

  • 1,第一次握手:客户端请求建立连接,向服务器发送一个同步报文(SYN=1),同时选择一个随机数(SN=x)作为起始序列号,并进入SYN_SENT状态,等待服务端确认
  • 2,第二次握手:服务端收到连接请求报文后,如果同意建立连接,则向客户端发送同步确认报文(SYN=1,ACK=1),确认号为ASN=x+1,同时选择一个随机数(SN=y)作为起始序列号,此时服务端进入SYN_RCVD状态
  • 3,第三次握手:客户端收到服务端的确认后,向服务端发送一个确认报文(ACK=1),确认号为(ASN=y+1),序列号为SN=x+1,客户端和服务器进入ESTABLISHED状态,完成三次握手。

24,TCP与UDP的区别?

  • 连接性:TCP是面向连接的协议,而UDP是无连接的协议;TCP建立连接,传输数据和断开连接都需要一定的时间和资源,而UDP直接发送数据包,不需要建立连接
  • 可靠性:TCP提供可靠的数据传输,确保数据按照顺序到达目的地,并且能够检测和纠正丢失或损坏的数据包;而UDP不提供可靠性,发送的数据包可能会丢失,重复,乱序或损坏,接收方无法得知
  • 效率:由于TCP需要建立连接和维护状态信息,因此在传输效率方面相对较低;而UDP没有这些开销,传输效率较高
  • 数据包大小:TCP将数据分割为较小的数据包进行传输,且每个数据包都有序号;UDP允许发送较大的数据包,但超过MTU(最大传输单元)时需要进行分片
  • 使用场景:TCP适用于要求数据可靠性和顺序性的应用,如http,ftp,smtp等;UDP适用于实时性要求较高,丢失少许数据不影响应用,如音视频传输,实时游戏等
  • 总结来讲:TCP提供可靠的,面向连接的传输,适用于数据完整性和顺序性较重要的应用;UDP提供无连接的,不可靠的传输,适用于实时性要求较高的应用
  • 选择使用哪种传输协议应根据具体应用需求来决定。

25,简单介绍一下HTTPS?

  • https=http+ssl,https是在http的基础上,通过ssl增加了一层加密协议,从而大大增加了http协议的安全性

26,说一下对称加密和非对称加密?

  • 对称加密是使用相同的密钥进行加密和解密,速度快但需要确保密钥安全共享
  • 非对称加密是使用对密钥,公钥用于加密,私钥用于解密,提供更好的安全性速度较慢
  • 对称加密适合大数据量的加密,例如文件传输;非对称加密适合安全通信,例如网络传输和数字签名
  • 常见的对称加密算法有AES,DES等;常见的非对称加密算法有RSA,ECC等

27,并发操作如何保证线程安全?

  • 锁和同步方法
  • 锁:同一时间只有一个线程能拿到锁,也就保证了同一时间只有一个线程能执行申请锁和释放锁之间的代码
  • 同步方法:或者同步代码块,使用关键字synchronized进行同步

28,什么是组件化开发?

  • 组件化架构的目的是让每一个业务模块变得相对独立,各个组件在组件模式下可以独立开发测试,集成模式下又可以集成到app壳工程里,从而得到一个具有完整功能的App

29,MVC,MVP,MVVM的区别?

  • 都是框架模式,目标都是为了解决Model和View的耦合问题
  • MVC:Model模型:专门用来封装和处理数据的,View视图:展示数据的,Controller控制器:专门来处理请求的,接收参数,调用service层代码,控制页面跳转
  • MVP:是在MVC上进化形成的,Presenter作为中间层负责M,V通信,解决两者的耦合问题
  • MVVM:Model专门用来处理数据,View展示页面,ViewModel视图和模型的转换,做到了数据的双向绑定

30,热修复的原理?

  • 让应用能够在无需重新安装的情况下实现更新,帮助应用快速建立动态修复能力
  • 从服务器下载修复好的dex包,下载到手机,替换原有的有bug的dex文件
  • 将出现bug的class单独的制作一份patch.dex文件(补丁包),然后在程序启动时,从服务器下载patch.dex保存到某个路径,再通过patch.dex的文件路径,用其创建Element对象,然后将这个Element对象插入到我们程序的类加载器PathClassLoader的pathList中的dexElements数组头部,这样在加载出现bug的class时会优先加载patch.dex中的修复类,从而解决bug

31,启动优化

  • Theme切换
  • 异步优化:使用子线程分担主线程任务,通过并行减少启动时间

32,全埋点是怎么做的?

  • 全埋点基本上都是围绕如何采集app click事件的,就是要自动找到那个被电击控件的点击处理逻辑,然后再利用一点的技术原理,对其进行处理,或者在其前面或者后面插入埋点代码逻辑,从而达到自动埋点的效果

33,多渠道打包

  • 友盟,美团Walle,Gradle

34,JetPack有过哪些组件?

  • Lifecycle:可以帮助管理Android组件的生命周期
  • ViewModel:提供了一个用于存储和管理UI相关数据的类
  • LiveData:可以在组件之间传递和观察数据
  • Room:提供了一个SQLite数据库的抽象层,更容易的进行本地数据存储
  • Navigation:更轻松的进行应用程序导航
  • Padding:更好的管理大型数据集合的加载和显示
  • DataBinding:将UI组件和数据模型绑定,无需写大量的findViewById代码

35,ViewModel的原理?

  • ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据,主要用来管理Activity/Fragment中的数据,还可以处理Fragment之间的通信
  • Activity的父类ComponentActivity实现了ViewModelStoreOwner接口,通过ViewModelProvider使用默认工厂创建了ViewModel,并通过唯一key值进行标识,存储到了ViewModelStore中,等下次需要的时候即可通过唯一key值进行获取。由于ComponentActivity实现了ViewModelStoreOwner接口,实现了getViewModelStore方法,当屏幕旋转的时候,会先调用onRetainNonConfigurationInstance()方法将ViewModelStore保存起来,然后再调用getLastNonConfigurationInstance()方法将数据恢复,如果为空的话,会重新创建ViewModelStore,并存储在全局中,以便下次发生变化时候,能够通过onRetainNonConfigurationInstance()方法保存起来。最后当页面销毁并且没有配置更改的时候,会将ViewModelStore中的数据进行清除操作。

36,LiveData的原理?

  • LiveData主要用于更新UI数据和组件之间传值
  • LiveData是一种持有可被观察数据的类,它通过观察者模式实现了数据变化的动态通知,即当观察者生命周期处于活跃状态时,能够感知数据的变化
  • 能够感知生命周期,内部通过Lifecycle来感知生命周期,在Activity,Fragment,Service中当对应生命周期为onDestory的时候,会销毁观察者,避免内存泄露
  • LiveData通过Observe和ObserveForever来订阅观察者,可以通过postValue和setValue来设置数据

37,LiveData是怎么做数据派发的?

  • setValue/postValue
  • 判断当前是否主线程,如果不是则报错
  • 版本号自增,数据源更新,分发事件逻辑
  • 判断是否分发中,如果是的话,忽略这次分发
  • 设置标识,判断参数中,有没指定Observer,如果有则只通知指定Observer,没有的话则遍历全部Observer通知
  • 判断如果当前监听器不活跃,则不分发
  • 二次确认监听器所在宿主是否活跃,如果不活跃,则证明Observer中mActive状态并非最新的,调用activeStateChanged
  • 判断版本号是否一致,如果一致则不需要分发
  • 对齐版本号,通知监听器

今日救赎先到这吧,下期见!

如果错误,请评论指正,谢谢!