Android开发涉及的知识点非常广泛,从界面布局、四大组件到构建工具、性能优化,任何一个环节都可能出现让人摸不着头脑的问题。很多问题在社区里被反复提问,形成了典型的FAQ高频问题。本文将围绕这些常见问题,从现象、原因、解决方案三个层面逐一展开分析,并配以代码示例,方便大家在实际项目中直接对照排查。

一、为什么Activity会被系统意外回收,如何保存和恢复状态?
这是Android FAQ中出现频率最高的问题之一。当屏幕旋转、系统内存不足或者用户长时间离开应用时,系统可能销毁并重建Activity。如果没有正确保存状态,用户输入的数据就会丢失,界面恢复到初始状态。
原因在于Activity的生命周期机制。当配置发生变化(如屏幕旋转)时,默认行为是销毁当前Activity再重新创建。解决方案有两种:一是重写onSaveInstanceState和onRestoreInstanceState方法手动保存恢复数据;二是在Manifest中声明android:configChanges属性,让Activity自行处理配置变化,避免重建。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 保存关键数据,注意数据量不宜过大
outState.putString("user_input", editText.getText().toString());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 恢复数据
String input = savedInstanceState.getString("user_input");
editText.setText(input);
}需要注意,onSaveInstanceState只适合保存少量轻量级临时数据,比如输入框内容、滚动位置等。如果是大量数据或复杂对象,建议使用ViewModel配合LiveData,因为ViewModel在配置变化时不会销毁,能跨屏幕旋转存活。另外,configChanges方案虽然省事,但会绕过系统默认的资源适配逻辑,除非有特殊需求,否则不推荐滥用。
二、应用频繁ANR是什么原因,如何定位和解决?
ANR即Application Not Responding,应用无响应。触发条件通常是主线程在规定时间内没有处理完任务:输入事件5秒内未响应、BroadcastReceiver的onReceive方法10秒内未执行完、前台Service20秒内未执行完。一旦超时,系统就会弹出ANR对话框,严重影响用户体验。
排查ANR的第一步是分析日志文件。可以借助adb命令导出trace文件,查看主线程当时正在执行的代码堆栈:
adb pull /data/anr/traces.txt ./traces.txt
常见的ANR原因包括:主线程执行了耗时的IO操作或复杂计算、主线程被锁阻塞、Binder调用等待超时、内存不足导致频繁GC等。定位到具体堆栈后,将耗时操作移到子线程是最直接的解法:
// 错误做法:主线程直接读文件
String content = readFileFromDisk();
// 正确做法:使用协程切到IO线程
lifecycleScope.launch(Dispatchers.IO) {
String content = readFileFromDisk();
withContext(Dispatchers.Main) {
textView.setText(content);
}
}除了移出主线程,还要注意死锁和锁竞争问题。比如主线程持有一把锁并等待网络返回,而网络回调线程又需要获取同一把锁,就会互相等待造成ANR。建议使用StrictMode在开发阶段开启主线程磁盘和网络操作的检测,提前发现问题。
三、内存泄漏有哪些典型场景,怎样排查?
内存泄漏在Android FAQ中同样榜上有名。典型场景包括:非静态内部类Handler持有Activity引用、单例对象持有Context、线程未及时结束、注册的监听器没有反注册、静态集合中累积对象未清理等。泄漏积累到一定程度会引发频繁GC甚至OOM崩溃。
以Handler为例,经典的泄漏写法如下:
// 存在泄漏风险的写法
public class MainActivity extends Activity {
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 匿名内部类隐式持有外部Activity引用
updateUI();
}
};
}修复方式是使用静态内部类加WeakReference,或者在onDestroy中调用handler.removeCallbacksAndMessages(null)移除所有未处理的消息:
private static class SafeHandler extends Handler {
private final WeakReference<MainActivity> reference;
SafeHandler(MainActivity activity) {
reference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = reference.get();
if (activity != null && !activity.isFinishing()) {
activity.updateUI();
}
}
}排查内存泄漏推荐使用Android Studio自带的Memory Profiler,操作步骤是:反复进入退出可疑页面,手动触发GC后抓取Heap Dump,观察Activity实例数量是否持续增长。也可以集成LeakCanary库,它会自动监控并生成泄漏引用链报告,是目前最省心的方案。
四、Gradle构建失败怎么办?常见报错逐一击破
构建问题是新手最容易卡住的地方。FAQ中出现较多的报错包括:依赖冲突、SDK版本不匹配、仓库源下载超时、缓存损坏等。
第一种是依赖冲突,报错信息通常提示Duplicate class。多模块项目中不同模块引入了同一个库的不同版本就会触发。解决方法是在模块的build.gradle中用exclude排除重复依赖,或者统一通过dependencies配置块强制指定版本。第二种是下载超时,国内网络访问Google Maven仓库经常失败,可以在settings.gradle中配置镜像源加速。
dependencyResolutionManagement {
repositories {
// 使用镜像源替代默认的google()仓库
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
}第三种是缓存损坏,表现为某些奇怪的任务失败。可以执行gradlew clean清理,必要时删除项目根目录下的.gradle文件夹和build目录后重新同步。第四种是SDK版本不匹配,检查compileSdkVersion、targetSdkVersion与依赖库要求的版本是否一致,同时确认本地SDK Manager中已安装对应版本的构建工具。
五、RecyclerView列表显示错乱或图片闪烁怎么处理?
列表错乱和图片闪烁是典型的复用机制引发的问题。RecyclerView为了性能会复用ItemView,如果在onBindViewHolder中没有完整地为每个位置设置数据,复用时就可能出现上一个条目的残留内容,表现为文本串行、图片显示错位。
正确做法是确保每次绑定都覆盖所有可变视图的状态,包括图片加载的占位处理:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Item item = data.get(position);
// 每次绑定都要重置,避免复用残留
holder.title.setText(item.getTitle());
Glide.with(holder.imageView.getContext())
.load(item.getImageUrl())
.placeholder(R.drawable.ic_placeholder)
.into(holder.imageView);
}图片闪烁通常是因为notifyDataSetChanged导致整个列表刷新,图片库重新加载引发闪动。改用DiffUtil或ListAdapter进行差量更新,只有真正变化的条目才会刷新,闪烁问题自然消失。此外,如果使用了ItemDecoration导致刷新跳动,检查是否在主线程重复计算了分割线偏移量。
六、总结与排查思路建议
以上这些问题虽然表现形式各异,但排查思路是相通的:先看日志定位现象,再分析生命周期或线程模型上的根因,最后选择最小侵入的修复方案。建议开发者养成三个习惯:一是遇到崩溃先看Logcat的完整堆栈而不是盲目搜索;二是熟练使用Profiler、Layout Inspector等官方工具;三是阅读官方文档中关于生命周期的章节,大量FAQ问题本质上都是对生命周期理解不到位造成的。把这些高频问题吃透,日常开发中的大部分障碍都能快速扫清。
Android FAQAndroid常见问题Android开发疑难解答修改时间:2026-09-02 05:40:31