android基于MVP,Retrofit2,RxJava2的天气app

最近学习了MVP,Retrofit2,RxJava2框架,感觉收获颇多,于是决定利用所学知识干一番大事业
这里写图片描述

ps:对这三种框架还不太清楚的童鞋可以看我之前的博客
传送门:
MVP
Retrofit2
RxJava2

效果图

话不多说,先上图
这里写图片描述
这里写图片描述
这里写图片描述

勉勉强强能看过去吧(●ˇ∀ˇ●)

那么最重要的来了

那就是

实现

首先,我这里用的后台api接口是和风天气的接口,完全免费,很实用,大家可以去注册一个
和风天气

这个接口会提供很多天气方面的信息,我们只需要取我们想要的就ok了

1.先修改一下build.gradle文件,引入依赖

//recyclerview
    implementation 'com.android.support:recyclerview-v7:28.+'
    //retrofit2
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
    //Rxjava and Retrofit(Retrofit+Rx需要添加的依赖)
    implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
    implementation 'io.reactivex:rxandroid:1.2.1'
    implementation 'io.reactivex:rxjava:1.2.1'
    //TextInputLayout
    implementation 'com.android.support:design:28.+'

2.看一下后台的数据样式

这里写图片描述

根据json格式构建我们的bean用于接收数据

由于bean类过长,这里我就不再展示了,有兴趣的朋友可以看我的源码

3.创建Retrofit的api接口,用于写请求数据的方法

public interface DataRequest {

    //获取天气数据,baseURL在model类里声明
    @GET("now")
    Observable<Weather> getNowWeather(@Query("location")String location,@Query("key")String key);

}

4.构建自己的MVP架构

我们先思考一下每层需要做的事情,

view:通过presenter从model层获取到数据并展示到界面上,因此我们构建一个setWeather方法,并传一个location用于告诉model层我们要获取哪里的数据

presenter:连接model和view,因此其中的方法就是model和view方法的集合

model:通过presenter从view层得到要获取哪里的数据,运用Retrofit向后台发出数据请求

工程的图纸有了,下面我们就该盖楼了!

MainContract

public class MainContract {

    public interface Presenter{

        //获取天气数据
        void getWeather(String location);

        //设置天气到view上
        void setWeather(List<Weather> weathers);
    }

    public interface View{

        //获取数据成功
        void getSuccess();

        //获取失败
        void getFailed();

        //把数据显示到view上
        void setWeather(List<Weather> weathers);

    }

}

MainPresenter(Presenter的具体实现)

public class MainPresenter implements MainContract.Presenter{

    private MainRepository mainRepository;

    private MainContract.View mainView;

    public MainPresenter(MainContract.View mainView) {
        mainRepository = new MainRepository(this);
        this.mainView = mainView;
    }

    @Override
    public void getWeather(String location) {
        mainRepository.getWeather(location);
    }

    @Override
    public void setWeather(List<Weather> weathers) {
        mainView.setWeather(weathers);
    }
}

MainRepository(请求数据方法的具体实现,其中运用了Retrofit+RxJava)

public class MainRepository {

    private final static String KEY = "你自己的key";

    private final static String TAG = "MainRepository";

    private final static String BASE_URL = "https://free-api.heweather.com/s6/weather/";

    private List<Weather> weathers = new ArrayList<>();

    private MainContract.Presenter presenter;

    public MainRepository(MainContract.Presenter presenter) {
        this.presenter = presenter;
    }

    /**
     * 获取天气数据
     * @param location 城市
     * @return Weather类的数据
     */
    public void getWeather(String location){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        DataRequest dataRequest = retrofit.create(DataRequest.class);
        dataRequest.getNowWeather(location,KEY)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Weather>() {
                    @Override
                    public void onCompleted() {
                        presenter.setWeather(weathers);
                        Log.d(TAG, "onCompleted: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: " + e.getMessage());
                    }

                    @Override
                    public void onNext(Weather weather) {
                        weathers.add(weather);
                        Log.d(TAG, "onNext: " + weather.getHeWeather6().get(0).getBasic().getLocation());
                    }
                });
        weathers.clear();
    }

}

MainActivity(视图层的具体实现,ps:部分代码)

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       init();
       onClick();
    }

    public void init(){
        presenter = new MainPresenter(this);
        editText = findViewById(R.id.et_city);
        tAdminArea = findViewById(R.id.t_admin_area);
        tCnty = findViewById(R.id.t_cnty);
        tCondTxt = findViewById(R.id.t_cond_txt);
        tFl = findViewById(R.id.t_fl);
        tHum = findViewById(R.id.t_hum);
        tLat = findViewById(R.id.t_lat);
        tLoc = findViewById(R.id.t_loc);
        tLocation = findViewById(R.id.t_location);
        tLon = findViewById(R.id.t_lon);
        tParentCity = findViewById(R.id.t_parent_city);
        tTmp = findViewById(R.id.t_tmp);
        tWindDir = findViewById(R.id.t_wind_dir);
        tWindSc = findViewById(R.id.t_wind_sc);
        tWindSpd = findViewById(R.id.t_wind_spd);
        bSearch = findViewById(R.id.b_search);
        background = findViewById(R.id.background);
        //隐藏标题栏
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.hide();
        }
    }

    public void onClick(){
        bSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sCity = editText.getText().toString();
                presenter.getWeather(sCity);
                Log.d(TAG, "onClick: " + sCity);
                //隐藏软键盘
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
            }
        });
        //回车键的监听
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
                if (i == EditorInfo.IME_ACTION_UNSPECIFIED) {
                    sCity = editText.getText().toString();
                    presenter.getWeather(sCity);
                    Log.d(TAG, "onClick: " + sCity);
                    //隐藏软键盘
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
                }
                return false;
            }
        });
    }

    @Override
    public void getSuccess() {
        Toast.makeText(getApplicationContext(),"获取数据成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void getFailed() {
        Toast.makeText(getApplicationContext(),"获取数据失败",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setWeather(List<Weather> weathers) {
        tWindSpd.setText("风速: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSpd() + "公里/小时");
        tWindSc.setText("风力: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSc() + "级");
        tWindDir.setText("风向: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindDir());
        tTmp.setText("温度: " + weathers.get(0).getHeWeather6().get(0).getNow().getTmp() + "℃");
        tParentCity.setText("市: " + weathers.get(0).getHeWeather6().get(0).getBasic().getParentCity());
        tLon.setText("经度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLon());
        tLocation.setText("地区: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
        tLat.setText("纬度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLat());
        tHum.setText("相对湿度: " + weathers.get(0).getHeWeather6().get(0).getNow().getHum());
        tFl.setText("体感温度: " + weathers.get(0).getHeWeather6().get(0).getNow().getFl() + "℃");
        tCondTxt.setText("天气状况: " + weathers.get(0).getHeWeather6().get(0).getNow().getCondTxt());
        tCnty.setText("国家: " + weathers.get(0).getHeWeather6().get(0).getBasic().getCnty());
        tAdminArea.setText("省: " + weathers.get(0).getHeWeather6().get(0).getBasic().getAdminArea());
        addWeatherPhoto();
    }

就这样,项目完成了是不是很简单?MVP架构让我们的整个项目都很清晰,Retrofit让我们能够轻松的实现网络请求,Rxjava配合Retrofit使用,整个代码成一条链式,并且可以自如的切换线程,简直太方便了!

这里写图片描述

能看我废话到这里的朋友我真的很感激,作为一个刚刚上路的小白,未来还有更多的路要走,希望能和大家一起进步,感谢大家的观看,上男神!

这里写图片描述

最后,附上我的github上的项目地址:
github传送门

猜你喜欢

转载自blog.csdn.net/qq_37918409/article/details/81666802