Android 单页应用如何在 Activity 与 Fragment 中共享状态
作者:Changing Lin
- 2021 年 12 月 10 日
本文字数:2590 字
阅读完需:约 8 分钟
1.需求
设计师在设计某个单页应用时,嵌入了多个标签页,而且每个标签页的业务逻辑有较高的重复性;按照以往的开发思路是,每个 Fragment 独立自身的业务逻辑,且与其他 Fragment 无关联,甚至与父 Activity 都无过多的关联,这种方式会带来一定的缺点,比如 数据同步问题、重复冗余代码、每个 Fragment 显得很沉重等。
那么有没有什么方法可以解决这个问题呢?答案是肯定的,Jetpack 库的 Lifecycle 组件。
2.知识点
Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者可将精力集中于真正重要的编码工作。
Lifecycle 生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。
3.源码
修改 build.gradle 来导入依赖:
dependencies {
val lifecycle_version = "2.4.0"
val arch_version = "2.1.0"
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata:$lifecycle_version")
// Lifecycles only (without ViewModel or LiveData)
implementation("androidx.lifecycle:lifecycle-runtime:$lifecycle_version")
// Saved state module for ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
// Annotation processor
annotationProcessor("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
// optional - helpers for implementing LifecycleOwner in a Service
implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
// optional - ReactiveStreams support for LiveData
implementation("androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version")
// optional - Test helpers for LiveData
testImplementation("androidx.arch.core:core-testing:$arch_version")
}
复制代码
父 Activity 的不完全代码:
public class CenterActivity extends BaseActivity {
private ViewPager viewPager;
private BottomNavigationView bottomNavigationView;
private TextView tvTitle;
private CenterViewModel viewModel;
private EmptyViewModel emptyViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pro);
bottomNavigationView = findViewById(R.id.nav_view);
viewPager = findViewById(R.id.view_pager);
ViewModelProvider provider = new ViewModelProvider(this); // 基于lifecycle-viewmodel来构建,并且参数是当前Activity,父类是ComponentActivity
emptyViewModel = provider.get(EmptyViewModel.class); // 构建EmptyViewModel对象
viewModel = provider.get(CenterViewModel.class); // 构建CenterViewModel对象
viewPager.setAdapter(viewModel.getAdapter(this));
viewPager.addOnPageChangeListener(onPageChangeListener);
bottomNavigationView.setOnNavigationItemSelectedListener(this::onNavigationItemSelected);
}
}
复制代码
子 Fragment 的不完全代码:
public class DashboardFragment extends Fragment {
private DashboardViewModel dashboardViewModel;
private FragmentDashboardBinding binding;
private MapView mMapView = null;
private MapViewModel mapViewModel;
private Bundle savedInstanceState;
private EmptyViewModel emptyViewModel;
private HomeViewModel homeViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
ViewModelProvider provider = new ViewModelProvider(getActivity()); // 基于lifecycle-viewmodel来构建,并且参数是父Activity,即上面的CenterActivity
dashboardViewModel = provider.get(DashboardViewModel.class);
binding = FragmentDashboardBinding.inflate(inflater, container, false);
View root = binding.getRoot();
final TextView textView = binding.textDashboard;
mMapView = binding.map;
mapViewModel = provider.get(MapViewModel.class);
this.savedInstanceState = savedInstanceState;
permissionConfigMap();
binding.ibCenter.setOnClickListener(this::onClick);
emptyViewModel = provider.get(EmptyViewModel.class); // 构建EmptyViewModel对象,请注意 此时的emptyViewModel对象与CenterActivity中的emptyViewModel是同一个对象
homeViewModel = provider.get(HomeViewModel.class);
binding.positionTitleView.setAdapter(emptyViewModel.getAdapter((BaseActivity) getActivity()));
return root;
}
}
复制代码
4.验证
通过添加日志打印,我们可以在日志窗口看到如下,至此 Activity 与 Fragment 中共享状态问题得到解决,我们可以把 状态存放到 ViewModel 中,便于访问。
2021-12-10 17:27:11.723 25482-25482/com.nufront.app_master E/cclin: [, , 0]:这里是CenterActivity:name.EmptyViewModel@2353d44a
2021-12-10 17:27:12.158 25482-25482/com.nufront.app_master E/cclin: [, , 0]:这里是DashboardFragment页面:name.EmptyViewModel@2353d44a
复制代码
划线
评论
复制
发布于: 4 小时前阅读数: 7
版权声明: 本文为 InfoQ 作者【Changing Lin】的原创文章。
原文链接:【http://xie.infoq.cn/article/283278b7593603c3c01bfbb08】。文章转载请联系作者。
Changing Lin
关注
获得机遇的手段远超于固有常规之上~ 2020.04.29 加入
我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。
评论