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

前言

之前一直搞不明白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,用法比较简单
接下来展示具体包接口

接下来讲解每一层的作用:

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

具体内容

先看model层里面的具体内容

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层
这里写图片描述

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层

这里的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,效果如图
这里写图片描述

这里写图片描述
这样就完成了一个比较标准的MVP项目的Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值