Fragment
概述
Fragment是Android中可重用的UI组件,它可以作为Activity的一部分嵌入到Activity中,也可以作为一个独立的UI容器。Fragment具有自己的生命周期,可以动态地添加、替换和移除。
生命周期
1. 基本生命周期方法
class MyFragment : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
// Fragment和Activity建立关联
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Fragment被创建
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// 创建Fragment的视图
return inflater.inflate(R.layout.fragment_my, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 视图创建完成
}
override fun onStart() {
super.onStart()
// Fragment可见
}
override fun onResume() {
super.onResume()
// Fragment可交互
}
override fun onPause() {
super.onPause()
// Fragment失去焦点
}
override fun onStop() {
super.onStop()
// Fragment不可见
}
override fun onDestroyView() {
super.onDestroyView()
// Fragment视图被销毁
}
override fun onDestroy() {
super.onDestroy()
// Fragment被销毁
}
override fun onDetach() {
super.onDetach()
// Fragment和Activity解除关联
}
}Fragment管理
1. 添加Fragment
supportFragmentManager.beginTransaction()
.add(R.id.container, MyFragment())
.commit()2. 替换Fragment
supportFragmentManager.beginTransaction()
.replace(R.id.container, NewFragment())
.addToBackStack(null)
.commit()3. 移除Fragment
supportFragmentManager.beginTransaction()
.remove(fragment)
.commit()Fragment通信
1. Fragment与Activity通信
// 1. 接口回调
class MyFragment : Fragment() {
interface OnFragmentInteractionListener {
fun onFragmentInteraction(data: String)
}
private var listener: OnFragmentInteractionListener? = null
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is OnFragmentInteractionListener) {
listener = context
}
}
}
// 2. ViewModel共享
class SharedViewModel : ViewModel() {
private val _data = MutableLiveData<String>()
val data: LiveData<String> = _data
}2. Fragment间通信
// 1. 通过Activity
parentFragmentManager.setFragmentResultListener("requestKey", viewLifecycleOwner) { key, bundle ->
val result = bundle.getString("bundleKey")
}
// 2. 通过ViewModel
class SharedViewModel : ViewModel() {
private val _sharedData = MutableLiveData<String>()
val sharedData: LiveData<String> = _sharedData
}面试常见问题
1. Fragment的生命周期和Activity的关系?
-
Fragment生命周期依赖于Activity:
- Activity暂停,Fragment必定暂停
- Activity销毁,Fragment必定销毁
-
生命周期对应关系:
- Activity onCreate() → Fragment onAttach() → onCreate()
- Activity onDestroy() → Fragment onDetach()
2. Fragment为什么要有setRetainInstance(true)?
-
作用:
- 在配置变更时保留Fragment实例
- 避免重新创建Fragment
- 保留数据状态
-
使用场景:
- 异步操作
- 数据缓存
- 配置变更处理
3. Fragment的懒加载如何实现?
class LazyFragment : Fragment() {
private var isFirstLoad = true
override fun onResume() {
super.onResume()
if (isFirstLoad) {
lazyLoad()
isFirstLoad = false
}
}
private fun lazyLoad() {
// 加载数据
}
}4. Fragment重叠问题如何解决?
-
问题原因:
- Activity重建导致Fragment重叠
- Fragment事务处理不当
-
解决方案:
- 使用add/hide代替replace
- 保存Fragment状态
- 正确使用事务
5. Fragment如何处理返回键事件?
class MainActivity : AppCompatActivity() {
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentById(R.id.container)
if (fragment is OnBackPressedListener) {
if (!(fragment as OnBackPressedListener).onBackPressed()) {
super.onBackPressed()
}
} else {
super.onBackPressed()
}
}
}6. Fragment的通信方式有哪些?
-
Fragment → Activity:
- 接口回调
- ViewModel共享
- EventBus
-
Fragment → Fragment:
- ViewModel共享
- Fragment Result API
- EventBus
7. Fragment的优势和使用场景?
-
优势:
- 模块化UI
- 重用性好
- 灵活的生命周期
-
使用场景:
- ViewPager页面
- 底部导航栏
- 分屏显示
最佳实践
-
生命周期管理
- 使用LifecycleObserver
- 合理处理状态保存
- 避免内存泄漏
-
通信机制
- 优先使用ViewModel
- 避免直接持有引用
- 使用Fragment Result API
-
性能优化
- 实现懒加载
- 合理使用事务
- 避免嵌套过深
注意事项
-
事务处理
- 正确使用commit()
- 合理使用回退栈
- 避免状态丢失
-
生命周期
- 注意Fragment重叠
- 处理配置变更
- 管理视图状态
-
内存管理
- 避免内存泄漏
- 及时释放资源
- 处理大数据加载