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

最近學(xué)習(xí)了MVP田柔,Retrofit2,RxJava2框架,感覺收獲頗多忧换,于是決定利用所學(xué)知識(shí)干一番大事業(yè)


549545057729183735.png

ps:對(duì)這三種框架還不太清楚的童鞋可以看我之前的博客
傳送門:
MVP
Retrofit2
RxJava2

效果圖

話不多說瘾婿,先上圖


44383753377195125.jpg
133482160071430163.jpg
270702073363472344.jpg
304578177432096238.jpg

勉勉強(qiáng)強(qiáng)能看過去吧(●ˇ?ˇ●)

那么最重要的來了

那就是

實(shí)現(xiàn)

首先蜻牢,我這里用的后臺(tái)api接口是和風(fēng)天氣的接口,完全免費(fèi)偏陪,很實(shí)用抢呆,大家可以去注冊(cè)一個(gè)
和風(fēng)天氣

這個(gè)接口會(huì)提供很多天氣方面的信息,我們只需要取我們想要的就ok了

dafc1839b30b10d8c75e5ede76c13a00.gif

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.看一下后臺(tái)的數(shù)據(jù)樣式

根據(jù)json格式構(gòu)建我們的bean用于接收數(shù)據(jù)

由于bean類過長(zhǎng)抱虐,這里我就不再展示了,有興趣的朋友可以看我的源碼

3.創(chuàng)建Retrofit的api接口揪罕,用于寫請(qǐng)求數(shù)據(jù)的方法

public interface DataRequest {

    //獲取天氣數(shù)據(jù)梯码,baseURL在model類里聲明
    @GET("now")
    Observable<Weather> getNowWeather(@Query("location")String location,@Query("key")String key);

}

4.構(gòu)建自己的MVP架構(gòu)

我們先思考一下每層需要做的事情宝泵,

view:通過presenter從model層獲取到數(shù)據(jù)并展示到界面上,因此我們構(gòu)建一個(gè)setWeather方法轩娶,并傳一個(gè)location用于告訴model層我們要獲取哪里的數(shù)據(jù)

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

model:通過presenter從view層得到要獲取哪里的數(shù)據(jù),運(yùn)用Retrofit向后臺(tái)發(fā)出數(shù)據(jù)請(qǐng)求

工程的圖紙有了鳄抒,下面我們就該蓋樓了闯捎!

MainContract

public class MainContract {

    public interface Presenter{

        //獲取天氣數(shù)據(jù)
        void getWeather(String location);

        //設(shè)置天氣到view上
        void setWeather(List<Weather> weathers);
    }

    public interface View{

        //獲取數(shù)據(jù)成功
        void getSuccess();

        //獲取失敗
        void getFailed();

        //把數(shù)據(jù)顯示到view上
        void setWeather(List<Weather> weathers);

    }

}

MainPresenter(Presenter的具體實(shí)現(xiàn))

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(請(qǐng)求數(shù)據(jù)方法的具體實(shí)現(xiàn),其中運(yùn)用了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;
    }

    /**
     * 獲取天氣數(shù)據(jù)
     * @param location 城市
     * @return Weather類的數(shù)據(jù)
     */
    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(視圖層的具體實(shí)現(xiàn)许溅,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);
        //隱藏標(biāo)題欄
        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);
            }
        });
        //回車鍵的監(jiān)聽
        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(),"獲取數(shù)據(jù)成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void getFailed() {
        Toast.makeText(getApplicationContext(),"獲取數(shù)據(jù)失敗",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setWeather(List<Weather> weathers) {
        tWindSpd.setText("風(fēng)速: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSpd() + "公里/小時(shí)");
        tWindSc.setText("風(fēng)力: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSc() + "級(jí)");
        tWindDir.setText("風(fēng)向: " + 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("經(jīng)度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLon());
        tLocation.setText("地區(qū): " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
        tLat.setText("緯度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLat());
        tHum.setText("相對(duì)濕度: " + 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("國(guó)家: " + weathers.get(0).getHeWeather6().get(0).getBasic().getCnty());
        tAdminArea.setText("省: " + weathers.get(0).getHeWeather6().get(0).getBasic().getAdminArea());
        addWeatherPhoto();
    }

就這樣瓤鼻,項(xiàng)目完成了是不是很簡(jiǎn)單?MVP架構(gòu)讓我們的整個(gè)項(xiàng)目都很清晰贤重,Retrofit讓我們能夠輕松的實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求茬祷,Rxjava配合Retrofit使用,整個(gè)代碼成一條鏈?zhǔn)讲⒒龋⑶铱梢宰匀绲那袚Q線程祭犯,簡(jiǎn)直太方便了!

4356c5bd92f761c685afb2c1e43def95.gif

能看我廢話到這里的朋友我真的很感激滚停,作為一個(gè)剛剛上路的小白沃粗,未來還有更多的路要走,希望能和大家一起進(jìn)步键畴,感謝大家的觀看最盅,上男神!

761589853486643181.jpg

最后起惕,附上我的github上的項(xiàng)目地址:
github傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涡贱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子疤祭,更是在濱河造成了極大的恐慌盼产,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勺馆,死亡現(xiàn)場(chǎng)離奇詭異戏售,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)草穆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門灌灾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人悲柱,你說我怎么就攤上這事锋喜。” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵嘿般,是天一觀的道長(zhǎng)段标。 經(jīng)常有香客問我,道長(zhǎng)炉奴,這世上最難降的妖魔是什么逼庞? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮瞻赶,結(jié)果婚禮上赛糟,老公的妹妹穿的比我還像新娘。我一直安慰自己砸逊,他們只是感情好璧南,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著师逸,像睡著了一般司倚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篓像,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天对湃,我揣著相機(jī)與錄音,去河邊找鬼遗淳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛心傀,可吹牛的內(nèi)容都是我干的屈暗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼脂男,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼养叛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宰翅,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤弃甥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后汁讼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淆攻,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年嘿架,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓶珊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耸彪,死狀恐怖伞芹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤唱较,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布扎唾,位于F島的核電站,受9級(jí)特大地震影響南缓,放射性物質(zhì)發(fā)生泄漏胸遇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一西乖、第九天 我趴在偏房一處隱蔽的房頂上張望狐榔。 院中可真熱鬧,春花似錦获雕、人聲如沸薄腻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)庵楷。三九已至,卻和暖如春楣颠,著一層夾襖步出監(jiān)牢的瞬間尽纽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工童漩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弄贿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓矫膨,卻偏偏與公主長(zhǎng)得像差凹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子侧馅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容