1 Activity转Fragment步骤
1.1 基础步骤
-
增加Fragment类
根据Activity增加对应名称的Fragment类,实现以下生命周期方法:onCreate() onCreateView() ,其中onCreateView返回的view必须是Fragment布局的根视图 -
分析原Activity
分析Activity是否包含Toolbar、NavigationView,如果都包含的话新增Fragment继承AppBarBaseFragment,不包含的话继承基础BaseFragment -
修改Activity的布局
修改Activity的布局要增加的Fragment,这里使用FrameLayout代替,后续通过代码将Fragment添加到该FrameLayout中 -
定义Fragment的布局
将Activity中布局(包括Toolbar、NavigationView)添加到Fragment中 -
修改Fragment内容
先改Fragment类的内容,修改中常遇到的问题可以参考下一节,更改完成无任何报错后,再删除Activity的内容,这样的方式可以避免修改有遗漏的地方 -
单元测试兼容
编译AndroidTest APK,确保自动化测试是兼容的,无问题。 -
主工程自检
主工程APK编译OK后,进行测试验证,确保功能OK
1.2 常见遇到的问题
-
在Fragment中getActivity 空指针的问题
【原因】Fragment已经onDetach activity了,此时通过getActivity去获取肯定为空。
【解决方法】在onAttach(Activity activity)时,初始化mContext,mActivity,onDetach时置为null -
Activity的onRestoreInstanceState 方法在Fragment中无此方法回调
【解决方法】在Fragment中onSaveInstanceState保存数据、onViewStateRestored恢复数据 -
Toolbar控件初始化问题
【原则】Toolbar属于Activity的应用栏, 目前Toolbar加载的NavigationView内容都是跟Fragment关联的,如果在Activity中初始化Toolbar,则Fragment中需要指定Activity来拿取Toolbar,这样耦合性太强,极不合理。综合考虑Toolbar放在Fragment中进行初始化。配置应用工具栏时,在Fragment中通过AppCompatActivity获取到ActionBar设置Toolbar -
NavigationView初始化加载布局问题
【原则】NavigationView被Toolbar加载,同时加载菜单项,这里需要放在Fragment中进行初始化。Fragment中Navigation需要被操作隐藏以及加载自定义的布局,放在Activity中无法直接拿到变量,不便于被替换操作。 -
ListView初始化问题
【原则】原来mListView是放在BaseActivity中进行的初始化,仔细查看可知BaseAcitivity中仅仅进行了初始化,无更多逻辑,这里不建议放在BaseActivity中,只有一行代码,单独拎出来即可。 -
状态栏回顶问题
【原则】状态栏回顶调用时,需要传入ListView,而ListView在Fragment中,故此处状态栏回顶只能放在Fragment中进行监听 -
onCreateDialog问题
【原则】简单改为showDialog,显示出Dialog即可 -
onNewIntent问题处理
【原则】onNewIntent是Activity中的方法,原来的实现可以改为通过Fragment对象来调用 -
NavigationView Toolbar初始化
【解决】放在基类初始化
2 架构指南
2.1 移动应用用户体验
请注意,移动设备的资源也很有限,因此操作系统可能会随时终止某些应用进程,以便为新的进程腾出空间。
鉴于这种环境条件,您的应用组件可以不按顺序地单独启动,并且操作系统或用户可以随时销毁它们。由于这些事件不受您的控制,因此您不应在应用组件中存储任何应用数据或状态,并且应用组件不应相互依赖。
2.2 常见的架构原则
如果您不应使用应用组件存储应用数据和状态,那么您应该如何设计应用呢?
分离关注点
要遵循的最重要的原则是分离关注点。一种常见的错误是在一个 Activity 或Fragment 中编写所有代码。这些基于界面的类应仅包含处理界面和操作系统交互的逻辑。您应使这些类尽可能保持精简,这样可以避免许多与生命周期相关的问题。
请注意,您并非拥有 Activity 和Fragment 的实现;它们只是表示 Android 操作系统与应用之间关系的粘合类。操作系统可能会根据用户互动或因内存不足等系统条件随时销毁它们。为了提供令人满意的用户体验和更易于管理的应用维护体验,您最好尽量减少对它们的依赖。
通过模型****驱动界面
另一个重要原则是您应该通过模型驱动界面(最好是持久性模型)。模型是负责处理应用数据的组件。它们独立于应用中的 View 对象和应用组件,因此不受应用的生命周期以及相关的关注点的影响。
持久性是理想之选,原因如下:
- 如果 Android 操作系统销毁应用以释放资源,用户不会丢失数据。
- 当网络连接不稳定或不可用时,应用会继续工作。
应用所基于的模型类应明确定义数据管理职责,这样将使应用更可测试且更一致。
2.3 推荐应用架构
3 屏幕兼容性
屏幕尺寸是系统为您的应用界面所提供的可见空间。 应用的屏幕尺寸并非设备的实际屏幕尺寸,而是综合考虑屏幕方向、系统装饰(如导航栏)和窗口配置更改(例如,当用户启用多窗口模式时)后的尺寸。
3.1 支持不同的屏幕尺寸
使用ConstraintLayout
如需创建适用于不同屏幕尺寸的自适应布局,最佳做法是将 ConstraintLayout 用作界面中的基本布局。使用ConstraintLayout,您可以根据布局中视图之间的空间关系指定每个视图的位置和大小。通过这种方式,当屏幕尺寸改变时,所有视图都可以一起移动和拉伸。
如需使用 ConstraintLayout 构建布局,最简单的方法是使用 Android Studio 中的布局编辑器。借助该工具,您可以将新视图拖动到布局中,将其约束条件附加到父视图和其他同级视图以及修改视图的属性,完全不必手动修改任何 XML。
如果您使用的是 LinearLayout,则也可以按布局权重展开子视图,以便每个视图按自身权重值所占的比例填充剩余的空间。但是,在嵌套的 LinearLayout 中使用权重将要求系统执行多次布局遍历以确定每个视图的尺寸,这会降低界面性能。幸运的是,ConstraintLayout 几乎能够构建 LinearLayout 所能构建的所有布局,而不会影响性能,因此您应该尝试将布局转换为 ConstraintLayout。
使用Fragment将界面组件模块化
在针对多种屏幕尺寸设计应用时,您希望确保不会在 Activity 之间不必要地重复界面行为。因此,您应该使用Fragment 将界面逻辑提取到单独的组件中。然后,您可以组合 Fragment 以便在大屏幕设备上运行时创建多窗格布局,或者在手机上运行时将 Fragment 放置在单独的 Activity 中。
例如,平板电脑上的一款新闻应用可能在左侧显示报道列表,而在右侧显示一篇完整的报道。在左侧选择一篇报道时,会更新右侧的报道视图。但是,在手机上,这两个组件应显示在单独的屏幕上。从列表中选择一篇报道时,会改变整个屏幕以显示这篇报道。
生命周期感知型组件的最佳做法
-
使界面控制器(Activity 和 Fragment)尽可能保持精简。它们不应试图获取自己的数据,而应使用ViewModel 执行此操作,并观察LiveData 对象以将更改体现到视图中。
-
设法编写数据驱动型界面,对于此类界面,界面控制器的责任是随着数据更改而更新视图,或者将用户操作通知给 ViewModel。
-
将数据逻辑放在 ViewModel 类中。ViewModel 应充当界面控制器与应用其余部分之间的连接器。不过要注意,ViewModel 不负责获取数据(例如,从网络获取)。ViewModel 应调用相应的组件来获取数据,然后将结果提供给界面控制器。
-
使用 Data Binding 在视图与界面控制器之间维持干净的接口。这样一来,您可以使视图更具声明性,并尽量减少需要在 Activity 和 Fragment 中编写的更新代码。如果您更愿意使用 Java 编程语言执行此操作,请使用诸如Butter Knife 之类的库,以避免样板代码并实现更好的抽象化。
-
如果界面很复杂,不妨考虑创建 presenter 类来处理界面的修改。这可能是一项艰巨的任务,但这样做可使界面组件更易于测试。
-
避免在 ViewModel 中引用View 或Activity 上下文。如果 ViewModel 存在的时间比 Activity 更长(在配置更改的情况下),Activity 将泄露并且不会由垃圾回收器妥善处置。
-
使用 Kotlin 协程管理长时间运行的任务和其他可以异步运行的操作。
网友评论