【安卓笔记】—— 页面导航 Navigation(3)

ViewModel、LiveData、DataBinding 和 Navigation的 结合

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

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

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

搭建界面

首先创建两个 Fragment ,我们将实现 Home 切换到 Detail
【安卓笔记】—— 页面导航 Navigation(3)_第1张图片
搭建 Home 页面:
【安卓笔记】—— 页面导航 Navigation(3)_第2张图片

搭建 Detail 页面:
【安卓笔记】—— 页面导航 Navigation(3)_第3张图片

连接 Home 与 Detail 的逻辑图:
【安卓笔记】—— 页面导航 Navigation(3)_第4张图片

在 activity_main.xml 中,放入 NavHostFragment
【安卓笔记】—— 页面导航 Navigation(3)_第5张图片

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


创建 ViewModel

创建一个继承自 View 的类 MyViewModel:
【安卓笔记】—— 页面导航 Navigation(3)_第6张图片

在 ViewModel 中管理一个变量 num:

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

DataBinding 绑定数据

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

dataBinding.enabled true

然后去 home 界面的 xml 中,将布局转化成 data binding 布局
【安卓笔记】—— 页面导航 Navigation(3)_第7张图片
然后在 xml 中设置变量(variable) data,获取 MyViewModel 中的变量

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

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

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

【安卓笔记】—— 页面导航 Navigation(3)_第8张图片

关于按键的动作绑定(例如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() {
            @Override
            public 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() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) { // 滑动进度条时
                myViewModel.getNum().setValue(i); // 将进度条的数字赋给 num
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
        
        return binding.getRoot();
    }



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

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

将 MyViewModel 中的变量绑定到 Detail 界面的 TextView上:
【安卓笔记】—— 页面导航 Navigation(3)_第9张图片
由于 Detail 界面的 “+” 与 “-” 按键动作与数据相关,因此通过DataBinding 绑定到界面上:
Button " - " 实现了数据 -1,添加如下代码:

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

【安卓笔记】—— 页面导航 Navigation(3)_第10张图片

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

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

【安卓笔记】—— 页面导航 Navigation(3)_第11张图片

而“返回按钮”与数据无关,因此在 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() {
            @Override
            public void onClick(View view) {
                NavController controller = Navigation.findNavController(view);
                controller.navigate(R.id.action_detailFragment_to_homeFragment2);
            }
        });

        return binding.getRoot();
    }

至此,功能全部写完,
运行效果如下:
滑动进度条,显示数字;
点击进入,切换页面;
点击+,数字变大;
点击返回,切换回初始界面。
【安卓笔记】—— 页面导航 Navigation(3)_第12张图片

你可能感兴趣的:(#,Android笔记)