分享一些重要的 Android 面试题,已拿 offer 附真题解析
1.选择路线有两种方式:1.无代理,那么在本地使用 DNS 查找到 ip,注意结果是数组,即一个域名有多个 IP,这就是自动重连的来源 2.有代理 HTTP:设置 socket 的 ip 为代理地址的 ip,设置 socket 的端口为代理地址的端口 3.代理好处:HTTP 代理会帮你在远程服务器进行 DNS 查询,可以减少 DNS 劫持。2.建立连接 1.连接池中已经存在连接,就从中取出(get)RealConnection,如果没有命中就进入下一步 2.根据选择的路线(Route),调用 Platform.get().connectSocket 选择当前平台 Runtime 下最好的 socket 库进行握手
3.将建立成功的 RealConnection 放入(put)连接池缓存 4.如果存在 TLS,就根据 SSL 版本与证书进行安全握手 5.构造 HttpStream 并维护刚刚的 socket 连接,管道建立完成 4.职责链模式:缓存、重试、建立连接等功能存在于拦截器中网络请求相关,主要是网络请求优化。网络请求的时候遇到的问题
线程同步的问题,常用的线程同步
1.sycn:保证了原子性、可见性、有序性
2.锁:保证了原子性、可见性、有序性
1.自旋锁:可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环。1.优点:线程被挂起的几率减少,线程执行的连贯性加强。用于对于锁竞争不是很激烈,锁占用时间很短的并发线程。2.缺点:过多浪费 CPU 时间,有一个线程连续两次试图获得自旋锁引起死锁 2.阻塞锁:没得到锁的线程等待或者挂起,Sycn、Lock3.可重入锁:一个线程可多次获取该锁,Sycn、Lock4.悲观锁:每次去拿数据的时候都认为别人会修改,所以会阻塞全部其他线程 Sycn、Lock5.乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。cas6.显示锁和内置锁:显示锁用 Lock 来定义、内置锁用 synchronized。7.读-写锁:为了提高性能,Java 提供了读 3.volatile
1.只能保证可见性,不能保证原子性 2.自增操作有三步,此时多线程写会出现问题 4.cas
1.操作:内存值 V、旧的预期值 A、要修改的值 B,当且仅当预期值 A 和内存值 V 相同时,将内存值修改为 B 并返回 true,否则什么都不做并返回 false。2.解释:本地副本为 A,共享内存为 V,线程 A 要把 V 修改成 B。某个时刻线程 A 要把 V 修改成 B,如果 A 和 V 不同那么就表示有其他线程在修改 V,此时就表示修改失败,否则表示没有其他线程修改,那么把 V 改成 B。3.局限:如果 V 被修改成 V1 然后又被改成 V,此时 cas 识别不出变化,还是认为没有其他线程在修改 V,此时就会有问题 4.局限解决:将 V 带上版本。5.线程不安全到底是怎么回事:
1.一个线程写,多个线程读的时候,会造成写了一半就去读 2.多线程写,会造成脏数据 ASYNCTASK 和线程池,GC 相关(怎么判断哪些内存该 GC,GC 算法)
1.Asynctask:异步任务类,单线程线程池+Handler
2.线程池:
1.ThreadPoolExecutor:通过 Executors 可以构造单线程池、固定数目线程池、不固定数目线程池。
2.ScheduledThreadPoolExecutor:可以延时调用线程或者延时重复调度线程。
3.GC 相关:重要
1.搜索算法:
1.引用计数
2.图搜索,可达性分析
2.回收算法:
1.标记清除复制:用于青年代
2.标记整理:用于老年代
3.堆分区:
1.青年区 eden 80%、survivor1 10%、survivor2 10%
2.老年区
4.虚拟机栈分区:
1.局部变量表
2.操作数栈
3.动态链接
4.方法返回地址
5.GC Roots:
1.虚拟机栈(栈桢中的本地变量表)中的引用的对象
2.方法区中的类静态属性引用的对象
3.方法区中的常量引用的对象
4.本地方法栈中 JNI 的引用的对象
JAVA 类加载过程:
1.加载时机:创建实例、访问静态变量或方法、反射、加载子类之前 2.验证:验证文件格式、元数据、字节码、符号引用的正确性 3.加载:根据全类名获取文件字节流、将字节流转化为静态储存结构放入方法区、生成 class 对象 4.准备:在堆上为静态变量划分内存 5.解析:将常量池中的符号引用转换为直接引用 6.初始化:初始化静态变量 MVC、MVP、MVVM:
1.mvc:数据、View、Activity,View 将操作反馈给 Activity,Activitiy 去获取数据,数据通过观察者模式刷新给 View。循环依赖 1.Activity 重,很难单元测试 2.View 和 Model 耦合严重 2.mvp:数据、View、Presenter,View 将操作给 Presenter,Presenter 去获取数据,数据获取好了返回给 Presenter,Presenter 去刷新 View。PV,PM 双向依赖 1.接口爆炸 2.Presenter 很重 3.mvvm:数据、View、ViewModel,View 将操作给 ViewModel,ViewModel 去获取数据,数据和界面绑定了,数据更新界面更新。1.viewModel 的业务逻辑可以单独拿来测试 2.一个 view 对应一个 viewModel 业务逻辑可以分离,不会出现全能类 3.数据和界面绑定了,不用写垃圾代码,但是复用起来不舒服 APK 瘦身:
1.classes.dex:通过代码混淆,删掉不必要的 jar 包和代码实现该文件的优化
2.资源文件:通过 Lint 工具扫描代码中没有使用到的静态资源
3.图片资源:使用 tinypng 和 webP,下面详细介绍图片资源优化的方案,矢量图
4.SO 文件将不用的去掉,目前主流 app 一般只放一个 arm 的 so 包
评论