Android 面试主题整理合集(一),android 开发前景
7.invalidate 与 requestLayout 区别
============================
view 调用 invalidate 将导致当前 view 的重绘,viewGroup 调用 invalidate 会使 viewGroup 的子 view 调用 draw
requestLayout 方法只会导致当前 view 的 measure 和 layout,而 draw 不一定被执行。只有当 view 的位置发生改变才会执行 draw 方法
8.View 和 ViewGroup 区别
==================
ViewGroup 的 onInterceptTouchEvent 默认返回 false,即不拦截事件,View 没有拦截事件方法,View 默认时消耗事件的
ViewGroup 默认不会调用 onDraw 方法,View 默认会调用 onDraw 方法。可以通过 setWillNotDraw(boolean willNotDraw)来指定是否调用 onDraw 方法
/**
If this view doesn't do any drawing on its own, set this flag to
allow further optimizations. By default, this flag is not set on
View, but could be set on some View subclasses such as ViewGroup.
Typically, if you override {@link #onDraw(android.graphics.Canvas)}
you should clear this flag.
@param willNotDraw whether or not this View draw on its own
*/
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
9.android 版本新特性
==============
5.0 引入 Material Design 主题
6.0 运行时权限
7.0 文件读写权限适配 FileProvider 移除了对 Apache HTTP 客户端的支持,建议使用 HttpURLConnection 代替。继续使用 Apache HTTP API,必须先在 build.gradle 文件中配置: android { useLibrary 'org.apache.http.legacy' } 复制代码
8.0 为所有通知分配渠道 app 内更新下载好的 apk 文件,需要用户开启未知应用安装权限
9.0 使用安全的网络访问,如果使用 http 请求会报错。Android 9.0 网络适配
10.0 存储空间分区存储,沙盒模式
10.Android 中一张图片占据的内存大小是如何计算
===========================
图片来源是 res 内的不同资源目录时,系统会根据设备当前的 dpi 值以及资源目录所对应的 dpi 值,做一次分辨率转换,规则如下:新分辨率 = 原图横向分辨率 * (设备的 dpi / 目录对应的 dpi ) * 原图纵向分辨率 * (设备的 dpi / 目录对应的 dpi )
其他图片的来源,如磁盘,文件,流等,均按照原图的分辨率来进行计算图片的内存大小
一张图片占用的内存大小的计算公式:分辨率 * 像素点大小;但分辨率不一定是原图的分辨率,需要结合一些场景来讨论,像素点大小就几种情况:ARGB_8888(4B)、RGB_565(2B) 等等
11.APP 启动速度优化
============
用 adb 命令可以检测启动时间,示例如下:
adb shell am start -W [packageName]/[.MainActivity]
./adb shell am start -W "com.hchstudio.dict"/".MainActivity"
WaitTime 为我们所关注的启动时间
app 的启动流程,主要需要减少 Application 和启动界面的 onCreate 方法
的 app 首页主题样式加上 android:windowBackground,放一下 app 的背景图片,这样即使 app 启动慢,也会首先加载背景,这样就会给用户造成一种假象,认为是 app 已经启动
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@color/colorLauncher</item>
</style>
12.内存抖动
=======
内存抖动是由于短时间内有大量对象进出新生区导致的,它伴随着频繁的 GC,gc 会大量占用 ui 线程和 cpu 资源,会导致 app 整体卡顿。
避免发生内存抖动的几点建议:
尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
注意自定义 View 的 onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
当需要大量使用 Bitmap 的时候,试着把它们缓存在数组或容器中实现复用。
对于能够复用的对象
,同理可以使用对象池将它们缓存起来。
13.Android 中 ClassLoader 的种类 &特点:
=============================
BootClassLoader(Java 的 BootStrap ClassLoader):
用于加载 Android Framework 层 class 文件。
PathClassLoader(Java 的 App ClassLoader):
只能加载已经安装过的 apk 的 dex 文件
DexClassLoader(Java 的 Custom ClassLoader):
可以从一个 jar 包或者未安装的 apk 中加载 dex 文件
BaseDexClassLoader:
是 PathClassLoader 和 DexClassLoader 的父类。
14.SharePreference 为什么不能存储较大 value
================================
public String getString(String key, @Nullable String defValue) {
synchronized (this) {
awaitLoadedLocked();
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
private void awaitLoadedLocked() {
while (!mLoaded) {
try {
wait();
} catch (InterruptedException unused) {
}
}
SharePreference 存值的时候,内部会有一个静态的 map 保存了你所有的 key 和 value
private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() {
if (sSharedPrefsCache == null) {
sSharedPrefsCache = new ArrayMap<>();
}
final String packageName = getPackageName();
ArrayMap<File, SharedPreferencesImpl> packagePrefs = sSharedPrefsCache.get(packageName);
if (packagePrefs == null) {
packagePrefs = new ArrayMap<>();
sSharedPrefsCache.put(packageName, packagePrefs);
}
return packagePrefs;
}
15.实现 View 滑动的几个办法
================
View 自身提供的 scrollTo()和 scrollBy 方法。但只适合对 View 内容的滑动
使用动画。但滑动后的 View 点击没有效果,所以适用于没有交互的 View
改变布局参数,比如 layoutParams.left。比动画稍微复杂,适合有交互的 View
Scroller 使用。调用 startScroll 方法,然后 invidate() --> View 会调用 onDraw(),里面会调用 computeScroll(),此方法默认空实现,需要自行实现 --> 重写 computeScroll(),实现滑动,如果没有结束,postInvalidate()重绘
16.事件分发
=======
源码
// 1. Activity 的 dispatchTouchEvent()方法
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
//交给 PhoneWindow 处理
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
// 2. PhoneWindow 的 superDispatchTouchEvent()方法
public boolean superDispatchTouchEvent(MotionEvent event) {
//交给 DecorView 处理
return mDecor.superDispatchTouchEvent(event);
}
// 3. 由于 DecorView 是 FrameLayout 子类,所以事件会被传递到 DecorView 的子 View 也就是,setContentView 设置的 View 中
View 的事件分发
17.View 的测量
==========
评论