Android 用MVVM框架模式+DataBinding+JSON来查询杭州天气信息(更新中)

Posted 彬sir哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 用MVVM框架模式+DataBinding+JSON来查询杭州天气信息(更新中)相关的知识,希望对你有一定的参考价值。

例子:

下面举一个简单的例子来实践MVVM模式。完整的项目代码下载GitHub上查看: MVVMDemo
例子实现的主要功能是:点击按钮网络查询天气,查询成功后在界面上显示天气信息。主界面如下图所示:

MVVM模式的代码组织结构建议按照业务功能进行划分,具体操作是:每个业务功能独立一个包存放,每个业务功能包下面再按Model、View、ViewModel分包存放。所有的Model存放在model包下面,所有的Activity和Fragment存放在activity包下面。所有的ViewModel存放在viewmodel包下面。该例子比较简单,只有一个weather业务功能模块,最终的代码组织结构如下图所示:

编写Model

查询杭州天气的URL为:
http://www.weather.com.cn/data/cityinfo/101210101.html
访问该URL将返回串JSON字符串,如下所示:


    "weatherinfo":
        "city":"杭州",
        "cityid":"101210101",
        "temp1":"5℃",
        "temp2":"20℃",
        "weather":"晴转多云",
        "img1":"n0.gif",
        "img2":"d1.gif",
        "ptime":"18:00"
    

按照此JSON字符串,可以编写相应的实体类。WeatherData类的代码如下所示:

public class WeatherData 

    private WeatherInfo weatherinfo;

    public WeatherInfo getWeatherinfo() 
        return weatherinfo;
    

    public void setWeatherinfo(WeatherInfo weatherinfo) 
        this.weatherinfo = weatherinfo;
    

WeatherInfo类的代码如下所示:

public class WeatherInfo 

    private String city;

    private String cityid;

    private String temp1;

    private String temp2;

    private String weather;

    private String img1;

    private String img2;

    private String ptime;

    public String getCity() 
        return city;
    

    public void setCity(String city) 
        this.city = city;
    

    public String getCityid() 
        return cityid;
    

    public void setCityid(String cityid) 
        this.cityid = cityid;
    

    public String getTemp1() 
        return temp1;
    

    public void setTemp1(String temp1) 
        this.temp1 = temp1;
    

    public String getTemp2() 
        return temp2;
    

    public void setTemp2(String temp2) 
        this.temp2 = temp2;
    

    public String getWeather() 
        return weather;
    

    public void setWeather(String weather) 
        this.weather = weather;
    

    public String getImg1() 
        return img1;
    

    public void setImg1(String img1) 
        this.img1 = img1;
    

    public String getImg2() 
        return img2;
    

    public void setImg2(String img2) 
        this.img2 = img2;
    

    public String getPtime() 
        return ptime;
    

    public void setPtime(String ptime) 
        this.ptime = ptime;
    

编写ViewModel

ViewModel不涉及任何的视图操作,只进行业务逻辑的处理。通过官方提供的Data Binding库,当ViewModel中的数据发生变化时,UI将自动更新。QueryWeatherViewModel的代码如下所示:

public class QueryWeatherViewModel 

    private static final String TAG = "QueryWeatherViewModel";

    public final ObservableBoolean loading = new ObservableBoolean(false);

    public final ObservableBoolean loadingSuccess = new ObservableBoolean(false);

    public final ObservableBoolean loadingFailure = new ObservableBoolean(false);

    public final ObservableField<String> city = new ObservableField<>();

    public final ObservableField<String> cityId = new ObservableField<>();

    public final ObservableField<String> temp1 = new ObservableField<>();

    public final ObservableField<String> temp2 = new ObservableField<>();

    public final ObservableField<String> weather = new ObservableField<>();

    public final ObservableField<String> time = new ObservableField<>();

    private Call<WeatherData> mCall;

    public QueryWeatherViewModel() 

    

    public void queryWeather() 
        loading.set(true);
        loadingSuccess.set(false);
        loadingFailure.set(false);

        mCall = RetrofitManager.get()
                .create(QueryWeatherRequest.class)
                .queryWeather();
        mCall.enqueue(new Callback<WeatherData>() 

            @Override
            public void onResponse(Call<WeatherData> call, Response<WeatherData> response) 
                WeatherInfo weatherInfo = response.body().getWeatherinfo();
                city.set(weatherInfo.getCity());
                cityId.set(weatherInfo.getCityid());
                temp1.set(weatherInfo.getTemp1());
                temp2.set(weatherInfo.getTemp2());
                weather.set(weatherInfo.getWeather());
                time.set(weatherInfo.getPtime());

                loading.set(false);
                loadingSuccess.set(true);
            

            @Override
            public void onFailure(Call<WeatherData> call, Throwable t) 
                if (call.isCanceled()) 
                    Log.i(TAG, "call is canceled.");
                 else 
                    loading.set(false);
                    loadingFailure.set(true);
                
            
        );
    

    public void cancelRequest() 
        if (mCall != null) 
            mCall.cancel();
        
    

编写View

View不涉及任何的业务逻辑的处理,只进行界面的显示。在xml布局文件中,通过官方提供的Data Binding库,将UI与ViewModel中的数据进行绑定,当ViewModel中的数据发生变化时,UI将自动更新。xml布局文件的代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View" />

        <variable
            name="viewModel"
            type="com.github.cyc.mvvmdemo.weather.viewmodel.QueryWeatherViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="@dimen/default_content_padding"
        tools:context="com.github.cyc.mvvmdemo.weather.activity.QueryWeatherActivity">

        <Button
            android:id="@+id/btn_query_weather"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:text="@string/query_weather"
            android:enabled="@viewModel.loading ? false : true"
            android:onClick="@() -> viewModel.queryWeather()" />

        <RelativeLayout
            android:id="@+id/vg_weather_info"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/btn_query_weather"
            android:layout_marginTop="@dimen/query_weather_margin"
            android:visibility="@viewModel.loadingSuccess ? View.VISIBLE : View.GONE">

            <TextView
                android:id="@+id/tv_city"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textStyle="bold"
                android:text="@string/city" />

            <TextView
                android:id="@+id/tv_city_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_city"
                android:layout_alignBottom="@id/tv_city"
                android:text="@viewModel.city"
                tools:text="杭州" />

            <TextView
                android:id="@+id/tv_city_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_city"
                android:layout_marginTop="@dimen/query_weather_margin"
                android:textStyle="bold"
                android:text="@string/city_id" />

            <TextView
                android:id="@+id/tv_city_id_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_city_id"
                android:layout_alignBottom="@id/tv_city_id"
                android:text="@viewModel.cityId"
                tools:text="101210101" />

            <TextView
                android:id="@+id/tv_temp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_city_id"
                android:layout_marginTop="@dimen/query_weather_margin"
                android:textStyle="bold"
                android:text="@string/temperature" />

            <TextView
                android:id="@+id/tv_temp1_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_temp"
                android:layout_alignBottom="@id/tv_temp"
                android:text="@viewModel.temp1"
                tools:text="5℃" />

            <TextView
                android:id="@+id/tv_tilde"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_temp1_value"
                android:layout_alignBottom="@id/tv_temp"
                android:text="@string/tilde" />

            <TextView
                android:id="@+id/tv_temp2_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_tilde"
                android:layout_alignBottom="@id/tv_temp"
                android:text="@viewModel.temp2"
                tools:text="10℃" />

            <TextView
                android:id="@+id/tv_weather"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_temp"
                android:layout_marginTop="@dimen/query_weather_margin"
                android:textStyle="bold"
                android:text="@string/weather" />

            <TextView
                android:id="@+id/tv_weather_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_weather"
                android:layout_alignBottom="@id/tv_weather"
                android:text="@viewModel.weather"
                tools:text="" />

            <TextView
                android:id="@+id/tv_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_weather"
                android:layout_marginTop="@dimen/query_weather_margin"
                android:textStyle="bold"
                android:text="@string/release_time" />

            <TextView
                android:id="@+id/tv_time_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/tv_time"
                android:layout_alignBottom="@id/tv_time"
                android:text="@viewModel.time"
                tools:text="10:00" />
        </RelativeLayout>

        <ProgressBar
            android:id="@+id/pb_progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="@viewModel.loading ? View.VISIBLE : View.GONE" />

        <TextView
            android:id="@+id/tv_query_failure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_con

以上是关于Android 用MVVM框架模式+DataBinding+JSON来查询杭州天气信息(更新中)的主要内容,如果未能解决你的问题,请参考以下文章

Android框架模式——MVVM

如何构建Android MVVM应用程序

Android进阶之MVVM+DataBinding框架模式(更新中)

Android基础——框架模式MVVM之DataBinding的实践

Android进阶之MVVM+DataBinding框架模式(更新中)

Android进阶笔记14:RoboBinding(实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架)