安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案

本文为学习笔记,所用的图片、案例均为教学视频截图

源视频地址:Navigation组件,让页面切换无比简单3
作者:longway777

目录

  • 实现效果
  • 一、创建两个空白的fragment
  • 二、创建viewmodle
  • 三、创建导航资源
  • 四、写fragment布局
  • 五、databinding
  • 六、fragment.java的编写:逻辑部分
  • 七、添加NavHostFragment
  • 完整代码

实现效果

通过在界面一滑动seekBar设置数值,把数值“带”到第二个界面,在第二个界面中加减改变数据后“带”到第一个界面。其实真正的实现并不是一个传输,而是基于viewModel的数据共享

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第1张图片

上一节是用bundle类实现数据传递:

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第2张图片这样就不得不面临一个问题:Activity随时可能摧毁,到时候还要保存数据,恢复数据,非常麻烦。而viewmodel很好的解决了这个问题。

因为viewmodel全时期存在!!跨越了各个activity和fragment的生命周期,少了生命周期带来的麻烦。
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第3张图片

activity和fragment很容易被销毁,每次销毁后我们都需要保存数据,当他们重新创建时又需要使数据重新呈现,非常麻烦。因为viewmodel贯穿了所有activity和fragment副本的生命周期,当不同的fragment进行切换的时候,就可以在viewmodel中进行数据的请求,viewmodel对所有的数据进行了统一的管理,这样可以使得应用程序的架构变得清晰。

一、创建两个空白的fragment

修改模板留下以下内容
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第4张图片

二、创建viewmodle

定义数据,数据获取的方法,数据变化的方法

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第5张图片ViewModel是数据的共享
在这里插入图片描述

三、创建导航资源

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第6张图片

四、写fragment布局

更改为约束布局做成下面界面:

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第7张图片

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第8张图片

五、databinding

要预先在gradel中设置,并且点击立即同步,sync now。
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第9张图片

转换为布局为 data binding layout

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第10张图片添加variable变量
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第11张图片
让textView显示viewModel中的数
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第12张图片

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第13张图片
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第14张图片

六、fragment.java的编写:逻辑部分

(1)获取myViewModel的实例化对象.

注意:第一个参数传入的必须是Fragment对应的Activity

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第15张图片(2)binding
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第16张图片

注意了,这个dataBind在fragment中编写和在activity中是有差别的。

在activity中用的是这个
在这里插入图片描述而在fragment中要使用的是这个
在这里插入图片描述

(3)nav按键导航
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第17张图片

(4)seekBar
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第18张图片

七、添加NavHostFragment

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第19张图片

完整代码

MyViewModel

public class MyViewModel extends ViewModel {
     
    //1.设置监听的数据,是私有的
    private MutableLiveData<Integer>number;
    //2.设置获取数据的方法,当为空时先进行实例化,初始化
    public MutableLiveData<Integer> getNumber() {
     
        if(number == null){
     
            number = new MutableLiveData<>();
            //不设置初始值,或者不对空进行判断,都会导致程序闪退
            //number.setValue(0);
        }
        return number;
    }
    //3.设置改变数据的方法
    public void add(int x){
     
        number.setValue(number.getValue() + x);
        Log.e("zhua", "number: "+number.getValue());
        if(number.getValue() < 0){
     
            number.setValue(0);
        }
    }
}

HomeFragment.java

public class HomeFragment extends Fragment {
     

    public HomeFragment() {
     
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
     

        //1.获取myViewModel的实例化对象
        MyViewModel myViewModel;
        //如果需要数据共享,这里,owner传入的必须是getActivity(),而不是this!!!!!
        myViewModel = new ViewModelProvider(getActivity(),
                new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);

        //2.获取binding的实例化对象(inflate),在activity中用的是setContentView
        /*FragmentHomeBinding binding = DataBindingUtil.inflate(inflater,
                R.id.homeFragment,container,false);*/

        //用了上面那一句导致app一直闪退进不去!!因为布局文件没有渲染!!
        FragmentHomeBinding binding;
        binding = DataBindingUtil.inflate(inflater,
                R.layout.fragment_home,container,false);

        //3.绑定viewmodel
        binding.setData(myViewModel);
        //4.获取fragment的activity
        binding.setLifecycleOwner(getActivity());
        //5.按键点击事件
        binding.button.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     
                //设置导航
                NavController controller = Navigation.findNavController(v);//这里有view,直接传递v进去
                controller.navigate(R.id.action_homeFragment_to_detailFragment);
            }
        });

        //当页面切回来的时候,先获取viewmodel中的数据,并设置进度
        binding.seekBar.setProgress(myViewModel.getNumber().getValue());

        binding.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
     
            @Override
            //将当前seekBar的进度写到viewModel中去(注意将seekBar的max设置为10)
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     
                myViewModel.getNumber().setValue(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
     

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
     

            }
        });

        //onCreateView要求的返回值是view,所以这里获取binding的根节点,这是一个view类型
        return binding.getRoot();
    }
}

对应的xml
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第20张图片其中对textView的数据绑定
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第21张图片

DetailFragment.java

public class DetailFragment extends Fragment {
     

    public DetailFragment() {
     
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
     

        //1.获取myViewModel的实例化对象
        MyViewModel myViewModel;
        myViewModel = new ViewModelProvider(getActivity(),
                new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);

        FragmentDetailBinding binding;
        binding = DataBindingUtil.inflate(inflater,
                R.layout.fragment_detail,container,false);

        //3.绑定viewmodel
        binding.setData(myViewModel);
        //4.获取fragment的activity
        binding.setLifecycleOwner(getActivity());
        //5.按键点击事件
        binding.button4.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     
                //设置导航
                NavController controller = Navigation.findNavController(v);//这里有view,直接传递v进去
                controller.navigate(R.id.action_detailFragment_to_homeFragment);
            }
        });

        //onCreateView要求的返回值是view,所以这里获取binding的根节点,这是一个view类型
        return binding.getRoot();
    }
}

安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第22张图片其中对textView的绑定和上面一样,对加减button的绑定;
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第23张图片
导航
安卓APP_ jetPack —— Navigation页面导航(3) + viewmodel :最佳的页面数据传递方案_第24张图片

你可能感兴趣的:(JetPack框架,移动开发,android,安卓)