
常见问题分类与解决方案
Activity生命周期相关问题
- 问题描述:屏幕旋转或配置更改导致
Activity
重建,数据丢失。 - 解决方案:
- 使用
onSaveInstanceState()
保存临时数据。 - 在
AndroidManifest.xml
中配置 android:configChanges
(不推荐,复杂场景慎用)。 - 使用
ViewModel
或 savedInstanceState
Bundle 持久化数据。
Fragment通信问题
- 问题描述:
Activity
与 Fragment
、Fragment
之间数据传递复杂。 - 解决方案:
- 直接通信:通过
getActivity()
或 requireActivity()
获取 Activity
实例。 - 间接通信:使用
ViewModel
共享数据(推荐)。 - 事件总线:如
LiveData
、EventBus
。
数据持久化选择
场景 | 推荐方案 | 说明 |
轻量级键值对存储 | SharedPreferences | 适合简单数据(如用户设置、登录状态)。 |
结构化数据存储 | Room + SQLite | 适合复杂数据关系,提供编译时校验和流畅API。 |
文件存储 | Internal/External | 存储大文件(如图片、视频),需处理权限和存储空间。 |
网络请求优化
- 问题:网络请求阻塞主线程、重复请求、缓存失效。
- 解决方案:
- 异步处理:使用
Retrofit
+ OkHttp
+ Coroutine
或 RxJava
。 - 缓存策略:
OkHttp
缓存、Room
本地缓存、WorkManager
离线处理。 - 请求合并:通过
Repository
模式统一管理网络请求。
代码示例与最佳实践
使用 ViewModel 保存数据
class MyViewModel : ViewModel() {
val data = MutableLiveData<String>().apply { value = "Initial Data" }
}
// 在 Activity 中
val viewModel: MyViewModel by viewModels()
viewModel.data.observe(this) { updateUI(it) }
Room 数据库定义
// Entity
@Entity(tableName = "user")
data class User(
@PrimaryKey val id: Int,
val name: String
)
// DAO
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
@Query("SELECT FROM user")
fun getAllUsers(): LiveData<List<User>>
}
// Database
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
Retrofit + Coroutine 网络请求
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): Response<User>
}
// 使用示例
val apiService = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
GlobalScope.launch(Dispatchers.IO) {
val user = apiService.getUser(123)
withContext(Dispatchers.Main) {
// 更新UI
}
}
工具与调试技巧
工具/技术 | 用途 | 关键功能 |
Android Studio Lint | 静态代码分析 | 检测代码规范、性能问题、潜在Bug。 |
Profiler | 性能分析 | 监控CPU、内存、网络、耗电情况。 |
LeakCanary | 内存泄漏检测 | 自动分析Activity/Fragment的内存泄漏。 |
Stetho | 调试工具 | 类似Chrome DevTools,调试网络、数据库、日志。 |
相关问题与解答
问题1:如何避免内存泄漏?
- 解答:
- 生命周期匹配:确保
Context
的生命周期与组件一致(如使用 ApplicationContext
代替 Activity
)。 - 解注册事件/订阅:在
onDestroy()
中移除 BroadcastReceiver
、EventBus
订阅、LiveData
观察者。 - 弱引用:使用
WeakReference
或 ViewModel
管理长生命周期数据。 - 静态内部类:避免持有外部类的隐式引用。
问题2:如何优化 RecyclerView 性能?
- 解答:
- 复用机制:设置稳定的
itemViewType
,避免频繁调用 onCreateViewHolder
。 - 懒加载:仅加载可见区域的图像(如
Glide
的 DiskCacheStrategy.AUTOMATIC
)。 - 局部刷新:使用
notifyItemChanged(position)
代替 notifyDataSetChanged()
。 - RecyclerPool:自定义
RecyclerView.RecycledViewPool
复用