Entrevista - Conceptos básicos de Android

"Este es el segundo día de mi participación en el Desafío de actualización de noviembre. Para obtener detalles del evento, consulte: Desafío de última actualización de 2021 "

¿Qué es la serialización y por qué introdujo Android Parcelable?

La llamada serialización consiste en convertir objetos en flujos binarios para facilitar su almacenamiento y transmisión.

  • Serializable es un conjunto de métodos de serialización implementados por Java, que pueden desencadenar operaciones de E/S frecuentes, lo cual es ineficiente y adecuado para almacenar objetos en el disco.
  • Parcelable es un mecanismo de serialización proporcionado por Android, que escribe el flujo de bytes serializado en una memoria común, y otros objetos pueden leer el flujo de bytes de esta memoria compartida y deserializarlo en un objeto. Por lo tanto, la eficiencia es relativamente alta y es adecuada para transferir información entre objetos o entre procesos.

Calcule el tamaño de la memoria ocupada por un mapa de bits

Tamaño de memoria de bitamp = píxel de ancho x (inTargetDensity / inDensity) x píxel de alto x (inTargetDensity / inDensity) x memoria ocupada por un píxel

Nota: aquí inDensity representa los dpi de la imagen de destino (en qué carpeta de recursos se coloca), e inTargetDensity representa los dpi de la pantalla de destino, por lo que puede encontrar que inDensity e inTargetDensity
estirarán el ancho y el alto del mapa de bits, por lo tanto cambiando el tamaño de la memoria ocupada por el mapa de bits.

Hay dos formas de obtener la huella de memoria en Bitmap.

  • getByteCount(): agregado en API12, representa la memoria mínima requerida para almacenar píxeles de mapa de bits.
  • getAllocationByteCount(): agregado en API19 para representar el tamaño de memoria asignado para Bitmap en la memoria, en lugar del método getByteCount().

Cuando el mapa de bits no se reutiliza, los resultados devueltos por getByteCount() y getAllocationByteCount son los mismos. Cuando se decodifica una imagen mediante el mapa de bits multiplexado, getByteCount() indica el tamaño de la memoria ocupada por la imagen recién decodificada y getAllocationByteCount() indica el tamaño real de la memoria ocupada por el mapa de bits multiplexado (es decir, la longitud de mBuffer).

¿Cómo carga Android grandes imágenes HD sin compresión?

Carga de diseño con BitmapRegionDecoder

¿Cuál es la diferencia entre PathClassLoader y DexClassLoader?

  • PathClassLoader: solo se pueden cargar los archivos APK que se han instalado en el sistema Android, es decir, el directorio /data/app, que es el cargador de clases predeterminado de Android.
  • DexClassLoader: puede cargar archivos dex, jar, apk, zip en cualquier directorio.

¿Entiende la optimización de WebView y cómo mejorar la velocidad de carga de WebView?

En el cliente, antes de cargar la página H5, WebView debe inicializarse primero y el proceso de carga de la interfaz posterior se bloquea hasta que WebView se inicialice por completo.

Método de optimización:

  • precargar vista web
  • Mientras carga la vista web, solicite los datos de la página H5
  • La ejecución del script es lenta, lo que permite que el script se ejecute en último lugar sin bloquear el análisis de la página.
  • El DNS y los enlaces son lentos, lo que permite a los clientes reutilizar los nombres de dominio y los enlaces utilizados.
  • La ejecución del código del marco React es lenta y esta parte del código se puede dividir y analizar de antemano.

¿Entiende los complementos y las revisiones, cuál es la diferencia entre ellos y cómo funcionan?

  • Complemento: el complemento se refleja en la división de funciones. Extrae una función de forma independiente, la desarrolla de forma independiente, la prueba de forma independiente y la inserta en la aplicación principal. A su vez, el tamaño de la aplicación principal es menor.
  • Revisión: la revisión se refleja en las correcciones de errores, se da cuenta de que los errores conocidos se pueden corregir sin volver a publicar ni reinstalar.

利用PathClassLoader和DexClassLoader去加载与bug类同名的类,替换掉bug类,进而达到修复bug的目的,原理是在app打包的时候阻止类打上CLASS_ISPREVERIFIED标志,然后在热修复的时候动态改变BaseDexClassLoader对象间接引用的dexElements,替换掉旧的类。

目前热修复框架主要分为两大类:

  • Sophix:修改方法指针。
  • Tinker:修改dex数组元素。

如何做性能优化?

  • 节制的使用Service,当启动一个Service时,系统总是倾向于保留这个Service依赖的进程,这样会造成系统资源的浪费,可以使用IntentService,执行完成任务后会自动停止。
  • 当界面不可见时释放内存,可以重写Activity的onTrimMemory()方法,然后监听TRIM_MEMORY_UI_HIDDEN这个级别,这个级别说明用户离开了页面,可以考虑释放内存和资源。
  • 避免在Bitmap浪费过多的内存,使用压缩过的图片,也可以使用Fresco等库来优化对Bitmap显示的管理。
  • 使用优化过的数据集合SparseArray代替HashMap,HashMap为每个键值都提供一个对象入口,使用SparseArray可以免去基本对象类型转换为引用数据类想的时间。

如果防止过度绘制,如何做布局优化?

  • 使用include复用布局文件。
  • 使用merge标签避免嵌套布局。
  • 使用stub标签仅在需要的时候在展示出来。

MVC、MVP与MVVM之间的对比分析?

  • MVC:PC时代就有的架构方案,在Android上也是最早的方案,Activity/Fragment这些上帝角色既承担了V的角色,也承担了C的角色,小项目开发起来十分顺手,大项目就会遇到耦合过重,Activity/Fragment类过大等问题。
  • MVP:为了解决MVC耦合过重的问题,MVP的核心思想就是提供一个Presenter将视图逻辑I和业务逻辑相分离,达到解耦的目的。
  • MVVM:使用ViewModel代替Presenter,实现数据与View的双向绑定,这套框架最早使用的data-binding将数据绑定到xml里,这么做在大规模应用的时候是不行的,不过数据绑定是一个很有用的概念,后续Google又推出了ViewModel组件与LiveData组件。ViewModel组件规范了ViewModel所处的地位、生命周期、生产方式以及一个Activity下多个Fragment共享ViewModel数据的问题。LiveData组件则提供了在Java层面View订阅ViewModel数据源的实现方案。

requestLayout()、invalidate()与postInvalidate()有什么区别?

  • requestLayout():该方法会递归调用父窗口requestLayout()方法,直到触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为true,会触发onMesaure()与onLayout()方法,不一定会触发onDraw()方法。
  • invalidate():该方法递归调用父View的invalidateChildInParent()方法,直到调用ViewRootImpl的invalidateChildInParent()方法,最终触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为false,不会触发onMesaure()与onLayout()方法,当时会触发onDraw()方法。
  • postInvalidate():该方法功能和invalidate()一样,只是它可以在非UI线程中调用。

一般说来需要重新布局就调用requestLayout()方法,需要重新绘制就调用invalidate()方法。

描述一下View的绘制原理?

View的绘制流程主要分为三步:

  1. onMeasure:测量视图的大小,从顶层父View到子View递归调用measure()方法,measure()调用onMeasure()方法,onMeasure()方法完成测量工作。
  2. onLayout:确定视图的位置,从顶层父View到子View递归调用layout()方法,父View将上一步measure()方法得到的子View的布局大小和布局参数,将子View放在合适的位置上。
  3. onDraw:绘制最终的视图,首先ViewRoot创建一个Canvas对象,然后调用onDraw()方法进行绘制。onDraw()方法的绘制流程为:
    ① 绘制视图背景。
    ② 绘制画布的图层。
    ③ 绘制View内容。
    ④ 绘制子视图,如果有的话。
    ⑤ 还原图层。
    ⑥ 绘制滚动条。

Android哪些情况会导致内存泄漏?

  • 持有静态的Context(Activity)引用。
  • 持有静态的View引用,
  • 内部类&匿名内部类实例无法释放(有延迟时间等等),而内部类又持有外部类的强引用,导致外部类无法释放,这种匿名内部类常见于监听器、Handler、Thread、TimerTask
  • 资源使用完成后没有关闭,例如:BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap。
  • 不正确的单例模式,比如单例持有Activity。
  • 集合类内存泄漏,如果一个集合类是静态的(缓存HashMap),只有添加方法,没有对应的删除方法,会导致引用无法被释放,引发内存泄漏。
  • 错误的覆写了finalize()方法,finalize()方法执行执行不确定,可能会导致引用无法被释放。

什么是MeasureSpec

MeasureSpec代表一个32位int值,高两位代表SpecMode(测量模式),低30位代表SpecSize(具体大小)。
SpecMode有三类:

  • UNSPECIFIED 表示父容器不对View有任何限制,一般用于系统内部,表示一种测量状态;
  • EXACTLY 父容器已经检测出view所需的精确大小,这时候view的最终大小SpecSize所指定的值,相当于match_parent或指定具体数值。
  • AT_MOST 父容器指定一个可用大小即SpecSize,view的大小不能大于这个值,具体多大要看view的具体实现,相当于wrap_content。

请简述 retrofit 中,一个方法的执行流程

首先我们通过我们 create 出来的 retrofit 实例来调用接口方法。所有的 interface 方法都会在 java 动态代理机制的作用下,调用一个匿名类 new InvocationHandler 中的 invoke。在 invoke 中,会根据我们想调用的方法 method 构造出一个 serviceMethod,然后调用 serviceMethod.callAdapter.adapt(okHttpCall) 作为返回结果。

Al construir un serviceMethod, se construyen un convertidor y un callAdapter de acuerdo con el tipo de retorno del método en la interfaz. Entre ellos, el convertidor generalmente usa el convertidor gson. El convertidor gson puede convertir automáticamente los datos json devueltos por el servidor en una instancia de la clase modelo en java. La gran mayoría de la implementación de callAdapter consiste en recibir una instancia de okHttpCall en el constructor y luego delegar la puesta en cola y la ejecución en esta instancia de okHttpCall para su ejecución. Después de que okHttpCall obtenga los datos del servidor, utilizará serviceMethod.toResponse(body) para transformar los datos. Entre ellos, el convertidor se usa al convertir. Una vez completada la conversión de datos, se encapsula en una respuesta y se pasa a la persona que llama. donde R es nuestra clase de datos.

¿Cómo completa ARouter la comunicación entre componentes?

  1. Adopte la tecnología APT del compilador, escanee anotaciones personalizadas en la fase de compilación, obtenga información de submódulos a través de anotaciones y regístrelas en la tabla de enrutamiento
  2. Operación de direccionamiento, buscando la información del submódulo registrado en la tabla de enrutamiento para completar la interacción.

¿Qué es ThreadLocal?

ThreadLocal es un tipo especial de variable en Java. ThreadLocal proporciona una copia de la variable para cada subproceso, de modo que cada subproceso no acceda al mismo objeto en un momento determinado, aislando así el intercambio de datos entre varios subprocesos.

En la implementación interna, cada subproceso tiene un ThreadLocalMap dentro, que se utiliza para guardar una copia de las variables que posee cada subproceso.

Supongo que te gusta

Origin juejin.im/post/7026596528311500808
Recomendado
Clasificación