欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android设计模式-MVP模式初步摸索

程序员文章站 2022-05-12 20:01:44
...

前言

之前一直搞不明白Android里面的MVP模式是怎么实现的,今天在导师的讲解下豁然开朗,这里要好好感谢一下导师。本文的重点就是通过代码的讲解来实现一个MVP模式下的天气查询的Demo。

准备环境

天气接口还是采用的和风天气的接口,这里给出和风天气的链接,需要的伙伴可以去官网注册使用:https://www.heweather.com/documents/api/v5/now

导入一下必要的包,这里我们使用RxJava+Retrofit来进行网络请求

    compile 'com.jakewharton:butterknife:8.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    apt 'com.jakewharton:butterknife-compiler:8.0.0'

还有一个ButterKnife依赖注入框架,具体用法自行Google,用法比较简单
接下来展示具体包接口
Android设计模式-MVP模式初步摸索
接下来讲解每一层的作用:

  • model层:用来存放实体类,数据获取的一些类与接口,获取数据的具体操作放在这一层
  • presenter:中间层,用来将model层获取到的数据与view进行交互传输,同时可以通过接口监听model层与view层的状态
  • view层:用来存放UI控件,处理UI与数据的简单逻辑,将数据绑定至UI等等

具体内容

先看model层里面的具体内容
Android设计模式-MVP模式初步摸索

Weather是实体类,这个就不用看了
WeatherModel 定义 WeatherModelImpl要执行的内容

public interface WeatherModel {
    //OnWeatherListener是Presenter层定义的接口,用来监听model层的状态
    void loadWeather(String cityName, OnWeatherListener listener);
}

WeatherModelImpl 这是具体的数据操作类包括了网络请求, 这里采用RxJava +Retrofit实现

public class WeatherModelImpl implements WeatherModel {
    private Retrofit retrofit;
    private static final String key = "81d241f5110048baa04dba7d1fb48948";
    @Override
    public void loadWeather(String cityName, OnWeatherListener listener) {
          retrofit = InitNetWorkRequest.baseRequset();
          NetWorkService netWorkService = retrofit.create(NetWorkService.class);
          Observable<Weather> observable = netWorkService.getCity(cityName,key);
          observable.subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(new Observer<Weather>() {
                      @Override
                      public void onSubscribe(@NonNull Disposable d) {
                      }
                      @Override
                      public void onNext(@NonNull Weather weather) {
                            listener.onSuccess(weather);      //请求数据成功则调用OnWeatherListener接口的onSuccess()方法将Weather信息发送到Presenter层
                      }

                      @Override
                      public void onError(@NonNull Throwable e) {
                            listener.onError();   //失败则调用onError()
                      }
                      @Override
                      public void onComplete() {

                      }
                  });

    }
}

接下来看presenter层
Android设计模式-MVP模式初步摸索

OnWeatherListener 用来监听model层的状态,包括转发数据

public interface OnWeatherListener {

    void onSuccess(Weather weather);  //成功

    void onError();  //出错
}

WeatherPresenter

public interface WeatherPresenter {
    //WeatherPresenterImpl要实现的接口,用来控制数据的流向
    interface IPresenter{      
        void getWeather(String cityName);   
    }
    //要和view层绑定的接口,用来获取数据
    interface IView {
        void onSuccess(Weather weather);
        void onFail();
    }
}

WeatherPresenterImpl 数据控制流向的具体操作类

public class WeatherPresenterImpl implements WeatherPresenter.IPresenter {
    private WeatherPresenter.IView mView;   
    private WeatherModelImpl model = null;  

    public WeatherPresenterImpl(WeatherPresenter.IView view ) {
        mView = view;                     //得到view
        model = new WeatherModelImpl();   //得到数据操作的实体类
    }

    @Override
    public void getWeather(String cityName) {
        model.loadWeather(cityName, new OnWeatherListener() {   //绑定监听器
            @Override
            public void onSuccess(Weather weather) {
                mView.onSuccess(weather);    //获取Weather信息成功就将信息发送给View
            }
            @Override
            public void onError() {
                mView.onFail();           //失败则处理对应逻辑
            }
        });
    }
}

接下来看View层
Android设计模式-MVP模式初步摸索
这里的view层比较简单,就一个Activity

public class MainActivity extends AppCompatActivity implements WeatherPresenter.IView {
    private  WeatherPresenterImpl mPresenter = null;
    @BindView(R.id.et_cityname)
    EditText et_cityName;
    @BindView(R.id.tv_info)
    TextView tv_info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mPresenter = new WeatherPresenterImpl(this);  //实例化presenter
    }

    @OnClick(R.id.btn_query)
    public void onTest(View view){
        String cityName = et_cityName.getText().toString();
        if(cityName!=null && !cityName.equals("")){
            mPresenter.getWeather(cityName.trim());
        }else{
            Toast.makeText(this,"城市名输入有误!",Toast.LENGTH_SHORT).show();
        }
    }
    @Override
    //请求数据成功,进行TextView显示操作
    public void onSuccess(Weather weather) {
        try {
            List<Weather.HeWeather5Bean> list = weather.getHeWeather5();
            Weather.HeWeather5Bean.BasicBean basicBean = list.get(0).getBasic();
            Weather.HeWeather5Bean.NowBean nowBean = list.get(0).getNow();
            tv_info.setText(basicBean.getCity() + "\n" +
                    basicBean.getCnty() + "\n" +
                    basicBean.getId() + "\n" +
                    basicBean.getProv() + "\n" +
                    nowBean.getFl() + "\n"

            );
        }catch (NullPointerException e){
            Toast.makeText(this,"城市信息错误,请输入正确的城市",Toast.LENGTH_SHORT).show();

        }
    }

    @Override
    //请求数据失败则进行失败逻辑处理
    public void onFail() {
       Toast.makeText(this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
    }
}

这里贴出布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mvpdemo.view.MainActivity">

    <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
      <EditText
          android:id="@+id/et_cityname"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_weight="0.3"
          android:hint="请输入城市名"/>

       <Button
           android:id="@+id/btn_query"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_weight="1"
           android:text="查询"/>


    </LinearLayout>


    <TextView
        android:id="@+id/tv_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        />

</LinearLayout>

补上网络请求的代码
InitNetWorkRequest

ublic class InitNetWorkRequest {

    public static Retrofit baseRequset(){

        return  new Retrofit.Builder()
                   .baseUrl("https://free-api.heweather.com/v5/")
                   .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                   .addConverterFactory(GsonConverterFactory.create())
                   .build();
    }
}

NetWorkService

public interface NetWorkService {

    //实况天气,city与key都是请求中的字段
    @GET("now")
    Observable<Weather> getCity(@Query("city") String city,
                                @Query("key") String key);

}

另外不要忘了加上权限

  <uses-permission android:name="android.permission.INTERNET"/>

运行Demo,效果如图
Android设计模式-MVP模式初步摸索

Android设计模式-MVP模式初步摸索
这样就完成了一个比较标准的MVP项目的Demo