ViewModel、LiveData、DataBinding 和 Navigation的 结合

  • 搭建界面
  • 创建 ViewModel
  • DataBinding 绑定数据

ViewModel 核心作用:管理 Activity 中的数据
使用 ViewModel 管理 Navigation 导航当中的数据,可以实现切换页面数据不丢失,架构更加清晰

关于安卓搭建界面:是用图形化方式还是用代码:ConstraintLayout 布局的出现,使得图形化方式搭建界面变得十分便利。而在以前,ConstraintLayout出现之前,往往使用的是 RelativeLayout,使用图形化界面不方便,所以更倾向于用代码写界面。现在,利用图形化方式搭建界面是十分直观与方便的,建议使用图形化方式,没有必要再用代码写界面了

搭建界面

首先创建两个 Fragment ,我们将实现 Home 切换到 Detail

搭建 Home 页面:

搭建 Detail 页面:

连接 Home 与 Detail 的逻辑图:

在 activity_main.xml 中,放入 NavHostFragment

界面搭建完成,接下来是完善代码部分。


创建 ViewModel

创建一个继承自 View 的类 MyViewModel:

在 ViewModel 中管理一个变量 num:

public class MyViewModel extends ViewModel {private MutableLiveData<Integer> num; public MutableLiveData<Integer> getNum(){if(num == null){ // 不存则创建一个,初值为 0num = new MutableLiveData<>();num.setValue(0);}return num;}public void add(int x){num.setValue(num.getValue() + x);if(num.getValue() < 0){ // 数字不能 < 0num.setValue(0);}}
}

DataBinding 绑定数据

要使用 DataBinding ,需要在 build.gradle(Module:app) 下,android 的 defaultConfig 下添加一句话:

dataBinding.enabled true

然后去 home 界面的 xml 中,将布局转化成 data binding 布局

然后在 xml 中设置变量(variable) data,获取 MyViewModel 中的变量

<data><variablename="data"type="com.example.navviewmodel.MyViewModel" />
</data>

将 MyViewModel 中的变量绑定到 Home 界面的 TextView上:

android:text="@{String.valueOf(data.getNum())}"

关于按键的动作绑定(例如Button的OnClick()):一般与数据相关则通过DataBinding 绑定到界面上,与数据无关而仅与逻辑相关(例如界面跳转)一般在 Activity 或 Fragment 中写代码。

来到 HomeFragment.java :
编写 Button 动作,在导航控制器跳转页面时,无需像之前一样利用 bundle 存储数据,由于利用了 ViewModel 管理变量,只需跳转页面即可。

    public View onCreateView(LayoutInflater inflater, final ViewGroup container,Bundle savedInstanceState) {final MyViewModel myViewModel;myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);final FragmentHomeBinding binding;binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home,container, false);binding.setData(myViewModel);binding.setLifecycleOwner(getActivity());binding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {NavController controller = Navigation.findNavController(view); // 获取导航控制器controller.navigate(R.id.action_homeFragment_to_detailFragment); // Home -> Detail}});binding.seekBar.setProgress(myViewModel.getNum().getValue()); // 初始化进度条,使得数据不丢失binding.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) { // 滑动进度条时myViewModel.getNum().setValue(i); // 将进度条的数字赋给 num}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});return binding.getRoot();}

同理,来到 DetailFragment.java:
设置变量(variable) data,获取 MyViewModel 中的变量的

<data><variablename="data"type="com.example.navviewmodel.MyViewModel" />
</data>

将 MyViewModel 中的变量绑定到 Detail 界面的 TextView上:

由于 Detail 界面的 “+” 与 “-” 按键动作与数据相关,因此通过DataBinding 绑定到界面上:
Button " - " 实现了数据 -1,添加如下代码:

android:onClick="@{()->data.add(-1)}"

Button " + " 实现了数据 +1,添加如下代码:

android:onClick="@{()->data.add(+1)}"

而“返回按钮”与数据无关,因此在 DetailFragment.java 中写代码:

public View onCreateView(LayoutInflater inflater, final ViewGroup container,Bundle savedInstanceState) {MyViewModel myViewModel;myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);FragmentDetailBinding binding;binding = DataBindingUtil.inflate(inflater, R.layout.fragment_detail, container, false);binding.setData(myViewModel);binding.setLifecycleOwner(getActivity());binding.button4.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {NavController controller = Navigation.findNavController(view);controller.navigate(R.id.action_detailFragment_to_homeFragment2);}});return binding.getRoot();}

至此,功能全部写完,
运行效果如下:
滑动进度条,显示数字;
点击进入,切换页面;
点击+,数字变大;
点击返回,切换回初始界面。

【安卓笔记】—— 页面导航 Navigation(3)相关推荐

  1. 【安卓笔记】—— 页面导航 Navigation(2)

    Navigation 中的数据传递和过渡动画 创建一个简单的页面导航 传递静态数据 传递动态数据 自定义动画 transalate:移动 scale:缩放 rotate:旋转 创建一个简单的页面导航 ...

  2. 小牛的安卓笔记-----底部导航栏的实现以及用TabLayout+ViewPager+Fragment实现页面滑动切换

    昨夜西风凋碧树,独上高楼,望尽天涯路. 今天难得有时间,准备写一写我们在APP中经常用到的页面形式,废话不多说,直接一张图看看页面效果你就知道为啥是常用的页面形式.先看看逻辑和最后的效果是怎么样的: ...

  3. WinPhone学习笔记(一)——页面导航与页面相关

    最近学一下Windows Phone(接下来简称"WinPhone")的开发,在很久很久前稍探究一下WinPhone中对一些传感器的开发,那么现在就从头来学学WinPhone的开发 ...

  4. 微信小程序 小程序生命周期、页面导航/事件、WXS脚本(笔记)

    文章目录 1. 页面导航 1.1 声明式导航 1.2 编程式导航 1.3 导航传参 2. 页面事件 3. 生命周期 3.1 应用生命周期 3.2 页面生命周期 4. WXS脚本 4.1 什么是WXS ...

  5. 第二十四章:页面导航(五)

    导航变化 当您尝试使用ModalEnforcement和MvvmEnforcement程序时,您可能会对模态页面未能保留任何信息感到不安.我们都遇到了导航到用于输入信息的页面的程序和网站,但是当您离开 ...

  6. windows phone 学习之页面导航和数据传递

    创建一个windows phone 应用程序,在xaml文件里添加三个按钮和三个textblock,添加一个windows phone 页面(命名为SecondPage),同样也是添加三个按钮和三个t ...

  7. windows phone 页面导航(6)

    页面导航的例子我们使用的是两个页面,从第一个页面(MainPage)导航到第二个页面(SecondPage),然后可以从第二个页面导航到第一个页面 ,使用的os 7.1: 页面导航没有引入新的命名空间 ...

  8. 页面导航【WP7学习札记之七】

    本节是WP7学习札记的第七篇,讲述的内容摘要主要是将页面导航的两种方式.地址别名.页面之间的数据传递(包括传递字符串.和传递对象两种方式).回退按钮(重写Back键的事件),具体如下: 首先讲述下Wi ...

  9. jsf 导航_JSF页面导航示例教程

    jsf 导航 Page navigation is the redirection of a page based on the events performed for instance – on ...

最新文章

  1. 11岁姑娘挑战8分钟编程小程序!蚂蚁金服董事长井贤栋:欢迎加入
  2. 阿里笔试题—战报交流
  3. jQuery入门学习
  4. 时间处理总结(二)oracle
  5. pomelo获取客户端IP
  6. monterey系统怎么降级?macOS Monterey系统降回Big Sur的详细教程
  7. 嗨淘V12刷任务点赞系统源码手动派单版本
  8. 4G通信技术LTE介绍
  9. 人人都需要专利的原因
  10. python实现Longest Common Subsequence最长公共子序列算法
  11. 选择、冒泡、插入、快速排序
  12. 小程序Git版本管理
  13. 如何免费的、完整的把 PDF 转换为 Word?
  14. Aurora 64B66B IP核的硬件跑通
  15. ZYNQ产品生产拷机问题思考
  16. 【MySQL】连接查询
  17. icloud 照片同步_如何在线查看iCloud照片
  18. 选对Shopee货代对店铺影响有多大?星卓越货代系统为您分析
  19. ocr扫描识别软件操作步骤
  20. shell之未找到命令

热门文章

  1. IT行业的职员加班到底有没有价值?
  2. 苹果是世界最高市值的公司,为什么苹果公司没有出现首富?
  3. python入门——P42魔法方法:算数运算1
  4. P4 2019年人体姿态估计指引
  5. Qt4_IconEditor窗口部件
  6. 分层结构、协议、接口、服务
  7. Linux各个文件夹介绍
  8. 计算机网络class2(标准化工作及相关组织)
  9. openwrt添加模块时编译报No rule to make target `install'
  10. ssis导入xml_SSIS包中的XML任务概述