阅读 49

Android 面试题

Q:内存优化? 好处:避免oom,提高流畅度,减少内存占用提高后台存活率,减少异常发生

尽量使用静态内部类,避免使用非静态的内部类 能使用Application就不要使用activity 资源未close 监听器未注销 经典handler不是静态的 webview使用多进程 LeakCanary HashMap和spareArray;spareArray2个数组保存key和value,key是int避免装箱,查找key使用二分效率高,省内存轻量,删除只做标记,添加复用已删除标记的,尽量做到不扩增数组 慎用枚举类型占用内存大,dex包体积大 字符串拼接,会生成新的对象

Q:电量优化?

  1. 电量优化和绘制优化是关联的,如果cup占用高,电量自然也就耗电量高
  2. 定位根据需要来使用
  3. 尽量避免无限轮询网络请求
  4. 一些重量级操作,只有在手机充电时执行
  5. 当用户是WiFi时才后台预下载一些任务,自动播放视频;

Q:绘制优化?

  1. GPU Overdraw
  2. Hierarchy Viewer,LayoutInspector
  3. ConstraintLayout 和 Merge
  4. bitmap压缩inSimpleSize=2缩小一半 和 565
  5. RelativeLayout比线性布局测量次数多

Q:启动速度优化?

  1. 思路以空间换时间
  2. splash预加载数据和预加载view(AsyncLayoutInflater)
  3. 预判有缓存广告再去使用
  4. 自定义view使用clipRect,避免绘制不必要的地方
  5. ViewStub 按需加载
  6. draw和measure不要创建大量或过大对象,避免大GC和内存抖动
  7. 无限动画view高度写死,避免重新测量和layout布局,会导致父布局层层进行layout。应该只重写onDraw,每次动画执行就重绘就可以了;

Q:volatile关键字的作用? 1.保证不同线程对这个变量的可见性 2.禁止进行指令的重新排序 什么是原子操作? m = 6 是原子性操作,而 int m = 6; 不是原子性操作,它有2个操作,声明m变量和对m赋值为6

在双重检查的单例中, instance = new Singleton(); 不是原子操作会有3个步骤 1.new Singleton() 在堆申请内存 2.Singleton调用构造方法初始化变量 3.instance局部变量指向Singleton实例在堆中的内存

所以如果JVM重新排序执行代码,1-2-3 也可能是 1-3-2,这样多个线程访问,可能会取到一个instance是不为null, 但构造方法还没有执行的;

所以instance成员变量应该加volatile字段,这样在写操作时会有内存屏障,只有写完了,它是实例才不会为null。

Q:如何启动其他应用的Activity?

其activity在清单文件里 android:exported="true" 才允许其他APP访问; intent必须同时匹配activity的intent-filter中的 action 、category、data; 如果有多个intent-filter匹配任意一组就可以

Q:Activity的启动过程?

主线程调用到IPC,IPC回调回主线程;

startActivity一些列方法调用到ActivityManagerService的startActivity,与ActivityManagerService交互是进程间通信,ActivityManagerService回调到activityThread的内部类ApplicationThread的scheduleLaunchActivity()其方法调用Handler H , 执行了handleLaunchActivity()和performLaunchActivity()对activity对象的创建和启动;

Q:谈一谈Fragment的生命周期?

onAttach fragment和activity建立关联

onCreateView 创建视图

onDestroyView fragment布局被移除

onDetach fragment和activity解除关联

Q:ThreadPoolExecutor的工作策略?

先发核心线程池,放不下放任务队列,队列放不下开非核心线程执行,非核心线程也慢走拒绝策略(默认拒绝策略是抛异常)

Q:ThreadPoolExecutor的构造方法?

核心线程池大小

最大线程数量

非核心线程闲置存活时间

非核心线程闲置存活时间的单位

任务队列

拒绝策略

Q:什么是Drawable?

抽象类,有很多不同场景的子drawable; 默认res/drawable aapt 构建工具会进行无损压缩,256真彩PNG转成8位PNG,res/raw不会进行压缩;

Q:引用对象?

new Object()表示在堆申请了一个内存地址空间比如0x001,赋值给Java虚拟栈里的一个地址上

Object a = new Object();

Java虚拟机栈(b)指向了堆内存地址上0x001, a == b == 0x001

Object b = a;

所以堆内存0x001有2个栈内存指向它,a=null 切断了 a 指向堆内存的引用0x001,所以只剩下b指向堆了,b不会因为a=null变为null的; 0x001 因为有b的引用,GC是无法回收它的,一旦b为null了,0x001无引用了,GC就会回收它

a=null;

Q:Android事件分发机制?

dispatchTouchEvent:进行事件的分发(传递)。默认常见控件是没有重写的(如LinearLayout,button),走的都是父类ViewGroup或是View;

当是ViewGroup分发时,会调用onInterceptTouchEvent默认是false, 这时就会逆序遍历它的所有孩子,一旦孩子在点击范围内,并且孩子的dispatchTouchEvent返回true,停止循环这个事件就交给它处理了;孩子的dispatchTouchEvent是ViewGroup则重复走上面的逻辑,如果是View类型则直接会调用View的dispatchTouchEvent,默认直接调用onTouchEvent,onTouchEvent根据有点击事件就会返回true;

当是ViewGroup分发时,调用onInterceptTouchEvent返回true,则不会向孩子分发事件了,直接调用super.dispatchTouchEvent也就是View的方法,View的dispatchTouchEvent会调用onTouchEvent,ViewGroup自行可以重写它写自己的逻辑;

onInterceptTouchEvent:对事件进行拦截。该方法只在ViewGroup中有,View(不包含 ViewGroup)是没有的。

onTouchEvent 事件处理,View的实现默认有设置onClick onTouchListener 它都会返回true

场景:当一个父容器包裹2个子view,因为是逆序遍历,所有上层也就是父容器数组中后面的元素,会优先判断是否有消费这个事件,一旦消费了则会break循环;

Q:Android滑动冲突处理?

内部拦截: 父类在onInterceptTouchEvent中除了down返回false其余返回true; 子类根据场景在move中调用requestDisallowInterceptTouchEvent(true)表示要自己处理事件,down中写死requestDisallowInterceptTouchEvent(true)表示要事件的;

外部拦截: 父类根据onInterceptTouchEvent在move中判断是否要拦截事件;

Q: 2个图片分辨率尺寸一样,但后缀是PNG和JPG,把他们转成bitmap占用内存大小是否一致?

一样,因为比如ARGB8888是占4字节,1001004 = 40000字节,40kb; 内存占用和文件格式无关,文件格式和文件在硬盘的大小有关,PNG文件转成JPG占用硬盘会小;

Q:基本类型的成员变量存储在JVM哪里?

虽然是基本类型但是成员变量是对象的属性,对象创建是存储到堆中的,自然它的属性也会随之存储到堆中。 当基本类型在方法中时是存储到Java虚拟机栈中的。

文章分类
Android
文章标签