android、鸿蒙开发--第十四章-->Android MVVM 新闻天气App

一、 Android MVVM  概念讲解:

转载:https://blog.csdn.net/weixin_44715733/article/details/130772996

没有相关概念的,一定要先观看上面链接内容。

转载协程:Android协程_android 协程-CSDN博客

协程介绍请观看上面链接内容。

二、MVVM使用的前期准备工作:

先看看运行效果图:

1.引入相关依赖:

在项目级别build.gradle,引入dataBinding.

2.由于dataBinding继承于viewbinding,所以以前我们写的BaseActivity,BaseFragment依然可以使用。

3.BaseActivity中需要添加的点:

需要再onCreate中添加如下代码

if (binding is ViewDataBinding){
    (binding as ViewDataBinding).lifecycleOwner=this
}

在onDestroy()中移除

if (binding is ViewDataBinding) {
    (binding as ViewDataBinding).lifecycleOwner = null
}

在BaseFragment,也是在生命周期的开始添加和结束的时候移除,原理同上。

三、MVVM的简单使用:

 我们就接着在上一章的MVP应用上接着使用,新增天气模块,这个模块就使用MVVM模式。

我们看看MainActivity内容

我们在看看TabMainBinding布局:

这里我们优先看看TabNewsFragment,只有一点点变动,其他与上一章节的MainActivity一模一样。

//新闻模块
class TabNewsFragment :
    BaseMVPFragment<FragmentTabnewsBinding, List<TabNewsData>, TabNewsPresenter>() {

   //之所以需要再可见的时候去获取Tab数据。是因为是短时间类,接口调用多次,会被拦截
    private var isSetTab = false

    override fun initData(savedInstanceState: Bundle?) {}

    //界面可见
    override fun onResume() {
        super.onResume()
        if (!isSetTab) {
            LoadingDialogManager.loadingDialog(requireActivity(), "加载数据中") //启动一个弹出提示用户正在获取数据
            presenter.startGetData() //通过P层,获取数据
        }
    }


    override fun dataCall(state: Int, message: String, dataList: List<TabNewsData>?) {
        LoadingDialogManager.loadOff() // 这是获取到数据。第一件事是关闭弹窗
        if (state == 200 && !dataList.isNullOrEmpty()) {
            isSetTab = true
            setNewsTab(dataList) //200即返回的List不为null 直接下一步操作
        } else {
            message.showToast() //否则看看返回的信息消息是什么。
        }
    }

    //这里是实现导航栏效果
    private fun setNewsTab(dataList: List<TabNewsData>) {
        val fragments = mutableListOf<Fragment>() //准备与之对应的Fragment
        dataList.forEach { //循环List,把每一Item放在对应的NewsFragment
            fragments.add(NewsFragment().apply {
//                这里 初始化数据传递给Fragment使用setArgumentsBundle args)方法
//                不可以使用构造方法传递参数,使用构造方法传递参数,数据会丢失
//                MyBundleUtils,一个封装类,Bundle 数据的封装
                arguments = MyBundleUtils.setKeyData(it)
            })
        }
        //这里是我封装的 tabLayout ViewPage2的一个封装类,
        NavigationBarHManager<ItemTabBinding, TabNewsData>(binding.tabLayout, binding.viewPager2)
            .setDataSources(fragments, dataList)
            .setOffscreenPageLimit(-1)
            .setTabMode(TabLayout.MODE_SCROLLABLE)
            .tabViewBinding { ItemTabBinding.inflate(layoutInflater) }
            .tabLinkage { binding, isChoose, data, _ ->
                binding.tvTabName.text = data.typeName
                binding.viewBg.visibility = if (isChoose) View.VISIBLE else View.INVISIBLE
            }
            .build(this)
    }
}

接下来我们正式进入天气模块(WeatherFragment)的MVVM的使用。

1.先看看WeatherFragment

接下来,我们看看FragmentWeatherBinding布局:

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <!--dataBinding 必须使用layout 包含你的布局-->
    <!--    这里data 可以是ViewModel,也可以是数据实体类,当然还有其他-->
    <!--    variable 可以设置多个,使用的时候,设置相关值即可-->
    <!--    viewModel-->
    <data>

        <variable
            name="viewModel"
            type="com.tmg.project.model.WeatherModel" />
        <!--        <variable-->
        <!--            name=""-->
        <!--            type="" />-->
    </data>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- 这里的内容text使用viewModel中的address-->
        <!--当其变化的时候,TextView的内容也会变化-->
        <!--这里dataBinding,会自动切换到主线程更新ui,不用担心子线程变更数据,出现异常-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="@{viewModel.address}"
            android:textSize="20sp"
            android:textStyle="bold" />
        <!--这里自定义了一个BindingAdapter方法,使用的viewModel.weatherListData-->
        <!--weatherListData数据变更,便会触发 setRecyclerViewAdapter方法-->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rvWeatherList"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="10dp"
            android:layout_weight="1"
            android:overScrollMode="never"
            app:setRecyclerViewAdapter="@{viewModel.weatherListData}" />

    </LinearLayout>
</layout>

我们看看setRecyclerViewAdapter自定义的方法:

我看看WeatherAdapter:

ItemWeatherBinding代码如下:

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="data"
            type="com.tmg.project.data.ForecastsData" />
    </data>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:paddingTop="10dp"
        android:paddingBottom="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:text="@{data.date}"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:text="@{data.week}"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="@{data.dayWeather}"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:gravity="center"
            android:text="@{data.nightTemp}"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="/"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="10dp"
            android:gravity="center"
            android:text="@{data.dayTemp}"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:textStyle="bold" />
    </LinearLayout>
</layout>

在接下来,我们看看WeatherModel内容:ViewModel是databinding自带的,所有MVVM的Model层都是继承于ViewModel。ViewModl,可以在设备切换的时候,保证数据不遗失。

接下来我们看看RetrofitManager调用的方法和返回数据内容(这里和上一章的RetrofitManager使用是一样的,使用公共的接口,不过在方法上有点变动)

接下来,我们看看WeatherData、ForecastsData

data class WeatherData(
    val address: String,
    val cityCode: String,
    val reportTime: String,
    val forecasts: List<ForecastsData>,
)

代码部分就差不多,只是简单的一个使用;后续使用肯定会更多。一起学习进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值