Android interview笔记

Android interview笔记

先记下大致题目和内容,简单记录,持续补充。

一、Android基础

1. basic

  • Serializable和Parcelable区别
SerializableParcelable
原理将对象进行序列化,将一个对象转换成可存储或可传输的状态。可以在网络上进行传输,也可以存储到本地。将一个完整的对象进行分解,分解后的每一部分都是Intent所支持的数据类型。
存储媒介使用IO读写存储在硬盘上直接在内存中读写,很明显内存的读写速度通常大于IO读写
实现使用反射,序列化和反序列化过程需要大量 I/O 操作自己实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在 Native 内存中,效率要快很多。
性能使用了反射,序列化的过程较慢,并会产生大量的临时变量,从而引起频繁的GC。更优

一个简单,但效率低;

一个高效,但使用麻烦。

世事两难全呀。

2. 组件

2.1 Activity

1)Activity lifecycle

onCreate() 创建活动,做一些数据初始化操作

onStart() 由不可见变为可见

onResume() 可以与用户进行交互,位于栈顶

onPause() 暂停,启动或恢复另一个活动时调用

onStop() 停止,变为不可见

onDestroy() 销毁

onRestart() 由停止状态变为运行状态

2) Activity的启动方式

①.standard模式

a.Activity的默认启动模式

b.每启动一个Activity就会在栈顶创建一个新的实例。例如:闹钟程序

缺点:当Activity已经位于栈顶时,而再次启动Activity时还需要在创建一个新的实例,不能直接复用。

②.singleTop模式

特点:该模式会判断要启动的Activity实例是否位于栈顶,如果位于栈顶直接复用,否则创建新的实例。 例如:浏览器的书签

缺点:如果Activity并未处于栈顶位置,则可能还会创建多个实例。

③.singleTask模式

特点:使Activity在整个应用程序中只有一个实例。每次启动Activity时系统首先检查栈中是否存在当前Activity实例,如果存在

则直接复用,并把当前Activity之上所有实例全部出栈。例如:浏览器主界面

④.singleInstance模式

特点:该模式的Activity会启动一个新的任务栈来管理Activity实例,并且该势力在整个系统中只有一个。无论从那个任务栈中启动该Activity,都会是该Activity所在的任务栈转移到前台,从而使Activity显示。主要作用是为了在不同程序中共享一个Activity

3) onCreateMenuOption 在Activity哪个生命周期被调用到?

onResume
复制代码

4)Activity & Window

二、各种原理 & 机制

View绘制

  • 工作flow
    • setContentView
    • 实例DecorView
    • 通过 LoadXmlResourceParser() 进行IO操作
    • 解析xml文件,通过反射 创建出View
    • 将View绘制在 DecorView上
      • ViewRootImpl
      • 通过performTraversals() 触发绘制流程
      • Cheographer
        • performMeasure 方法获取View的尺寸
        • performLayout 方法获取View的位置
        • 然后通过 performDraw 方法遍历View 进行绘制。
  • 绘制原理
    • CPU
      • 执行应用层的measure、layout、draw等操作,绘制完成后将数据提交给GPU.
    • GPU
      • 进一步处理和缓存数据
    • 屏幕
      • 以固定的频率(16.6ms,即1秒60帧)从缓冲区中取出数据来填充像素点.
  • 双缓冲机制
    • GPU只向Back Buffer中写入绘制数据,且GPU会定期交换Back Buffer和Frame Buffer,交换的频率也是60次/秒.
    • 应用正在往Back Buffer中填充数据时,系统会将Back Buffer锁定.
    • 当GPU发现Back Buffer被锁定了,它会放弃这次交换 —— 掉帧。
  • 布局加载原理
    • setContentView
      • 1.解析xml,获取XmlResourceParser,这是IO过程。
      • 2.通过createViewFromTag,创建View对象,用到了反射
  • 布局加载优化
    • 1.侧面缓解(异步加载)
      • AsyncLayoutInflater
    • 2.根本解决(不需要IO, 反射过程, 如X2C,Anko,Compose等)
    • 常规优化手段
      • 优化布局层级及复杂度
          • 1.使用ConstraintLayout,可以实现完全扁平化的布局,减少层级。
          • 2.RelativeLayout本身尽量不要嵌套使用。
          • 3.嵌套的LinearLayout中,尽量不要使用weight,因为weight会重新测量两次。
          • 4.推荐使用merge标签,可以减少一个层级。
          • 5.使用ViewStub延迟加载。
      • 避免过度绘制
        • 1.去掉多余背景色,减少复杂shape的使用。
        • 2.避免层级叠加。
        • 3.自定义View使用clipRect屏蔽被遮盖View绘制。

Binder机制

这块内容好多。。

先来个图看看,哈哈。

系统结构图。

Handler

先放点图

View事件分发

1) View 事件传递

Activity调用dispathTouchEvent()方法,把事件传递给Window;

Window再将事件交给DecorView(DecorView是View的根布局);

DecorView再传递给ViewGroup;

Activity ——> Window ——> DecorView ——> ViewGroup——> View

ViewRoot只是ViewTree的管理者,和View没有关系, 真正的根结点是DecorView。

2)事件分发的主要有三个关键方法

dispatchTouchEvent() 分发

onInterceptTouchEvent() 拦截 ,只有ViewGroup独有此方法

onTouchEvent() 处理触摸事件

app启动

大神的图。

开机启动过程:

app启动过程:

app性能优化

https://www.jianshu.com/p/b3b09fa29f65
复制代码

内存泄露

  • Handler 引起的内存泄漏
  • 单例模式引起的内存泄漏
  • 非静态内部类创建静态实例引起的内存泄漏
  • 非静态匿名内部类引起的内存泄漏
  • 注册/反注册未成对使用引起的内存泄漏
  • 资源对象没有关闭引起的内存泄漏
  • 集合对象没有及时清理引起的内存泄漏

启动优化

  • onCreate() 中不执行耗时操作
  • 把页面显示的 View 细分一下,放在 AsyncTask 里逐步显示,用 Handler 更好。这样用户的看到的就是有层次有步骤的一个个的 View 的展示,不会是先看到一个黑屏,然后一下显示所有 View。最好做成动画,效果更自然。
  • 利用多线程的目的就是尽可能的减少 onCreate() 和 onReume() 的时间,使得用户能尽快看到页面,操作页面。
  • 减少主线程阻塞时间。
  • 提高 Adapter 和 AdapterView 的效率。
  • 优化布局文件。

内存优化

  • 第一点: 如果只是想避免OutOfMemory异常的发生,则可以使用软引用。 如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。

  • 第二点: 可以根据对象是否经常使用来判断选择软引用还是弱引用。 如果该对象可能会经常使用的,就尽量用软引用。 如果该对象不被使用的可能性更大些,就可以用弱引用。

  • 系统化完善解决方案

    • 采集一些数据上报到服务器,然后传到后台,方便Bug跟踪人员或者是Crash跟踪人员进行一系列问题的解决。
  • 避免内存抖动

    • 避免在循环体内创建对象,应该把对象创建移到循环体外;
    • 当需要大量使用Bitmap的时候,试着把它们缓存在数组或容器中实现复用。
    • 对于能够复用的对象,同理可以使用对象池将它们缓存起来。

布局优化

网络库

1) Okhttp和Retrofit

拦截器使用什么设计模式?
复制代码

外观模式。通过okHttpClient这个外观去实现内部各种功能。

建造者模式。构建不同的Request对象。

工厂模式。通过OkHttpClient生产出产品RealCall。

享元模式。通过线程池、连接池共享对象。

责任链模式。将不同功能的拦截器形成一个链。

Questions

ANR的原因

如何统计页面桢率,app流畅?

https://www.jianshu.com/p/d126640eccb1
复制代码

Binder传递对象为什么需要序列化?Serialzable和Parcelable的区别?

  1. bundle传递数据时只支持基本数据类型,所以在传递对象时需要序列化转换成可存储或可传输的本质状态(字节流)
  2. Serializable 是序列化的意思,表示将一个对象转换成存储或可传输的状态。
  3. Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,实现传递对象的功能。

三、设计模式

1. 单例

参考

分类:
Android
标签: