Android 開發(fā)中的MVP模式結(jié)合RxJava杭措、OkHttpUtils的基本使用

在andorid開發(fā)中越來越多的見到MVP的身影拳话,做過web的開發(fā)的都知道web三層架構(gòu)珍剑,而我們的MVP也有異曲同工之處钓辆,下面我們看下MVP的總體架構(gòu)缕溉,將Model通過Prensenter完全與View隔離開來考传,大大減輕了View的負(fù)擔(dān)

MVP

下面以簡單的登錄模塊,來展示最基本的MVP

Login

根據(jù)基本的OOP原則证鸥,V僚楞、P、M層都使用了接口來實(shí)現(xiàn)枉层,當(dāng)然也可以不用這么麻煩泉褐。
首先看View接口內(nèi),展示我們登錄的結(jié)果,而LoginActivity則實(shí)現(xiàn)了LoginView接口鸟蜡,實(shí)現(xiàn)showLoginResult(String msg)方法膜赃,同時在onCreate方法中也對Presenter進(jìn)行了初始化,在登錄按鈕點(diǎn)擊時揉忘,調(diào)用Presenter的Login方法

public interface LoginView {
    void showLoginResult(String msg);
}
@Override
public void showLoginResult(String msg) {
   ToastUtil.shortToast(getApplicationContext(),msg);
}
@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_login);
     ButterKnife.inject(this);
     loginPresenter = new LoginPresenterImpl(this,LoginActivity.this);
     initData();
}
@OnClick(R.id.tv_login)
public void tvLogin(Button tv){
    String mobile=edtAccount.getText().toString().trim();
    if (!RegexTool.isMobile(mobile)){
         ToastUtil.shortToast(getApplicationContext(),"請輸入正確的11位手機(jī)號~~");
            return;
    }
    String password=edtPassword.getText().toString().trim();
     loginPresenter.login(mobile,password);
}

再來看我們的Presenter層接口跳座,最簡單的登錄方法接口,然后看到LoginPresenterImpl接口的實(shí)現(xiàn)類癌淮,所以我們可以在接口實(shí)現(xiàn)類LoginPresenterImpl的構(gòu)造方法中躺坟,進(jìn)行View和Model的初始化,在這里實(shí)現(xiàn)了Presenter的Login方法乳蓄,然后再調(diào)用Model的Login的方法咪橙,進(jìn)行網(wǎng)絡(luò)層的請求。
在Presenter層就同時持有View和Model虚倒,這樣我們就可以在P層處理Model返回的數(shù)據(jù)及View根據(jù)M所做的UI改變

public interface LoginPresenter {
    void login(String phone,String passWord);
}
public LoginPresenterImpl(LoginView loginView,Context context) {
      this.loginView = loginView;
      loginModel = new LoginModelImpl();
}

在Login方法里美侦,我們用到了RxJava、RxAndroid編程

 @Override
    public void login(final String phone, final String passWord) {
        subscription = loginModel.login(phone,passWord)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Subscriber<LoginBean>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        if (e!=null)
                       loginView.showLoginResult(e.getMessage());
                    }

                    @Override
                    public void onNext(LoginBean loginBean) {
                        String message = loginBean.getMessage();
                        loginView.showLoginResult(message);
                        String status = loginBean.getStatus();
                        if (status!=null&&status.equals("1")){
                            // ToDo
                        }
                    }
                });

    }

對于這一段代碼我們先不深究魂奥,首先看到是調(diào)用了Model的Login方法菠剩,我們看一下LoginModel及其實(shí)現(xiàn)類

public interface LoginModel {
    Observable<LoginBean> login(String phone, String passWord);
}
public class LoginModelImpl implements LoginModel {

    @Override
    public Observable<LoginBean> login(final String phone, final String passWord) {
           return Observable.create(new Observable.OnSubscribe<LoginBean>() {
               @Override
               public void call(Subscriber<? super LoginBean> subscriber) {
                   try {
                       Map<String ,String> params=new HashMap<>();
                       params.put(MemberController.Login.PARAMS.MOBILE,phone);
                    params.put(MemberController.Login.PARAMS.PASSWORD,passWord);
                       params.put(MemberController.Login.PARAMS.LOGINTYPE,"0");

                       Response response = OkHttpUtils
                               .post()
                               .url(MemberController.Login.URL)
                               .params(params)
                               .build().execute();
                        String result=response.body().string();
                       LoginBean loginBean = new Gson().fromJson(result, LoginBean.class);
                       subscriber.onNext(loginBean);
                       subscriber.onCompleted();
                   } catch (IOException e) {
                       e.printStackTrace();
                       subscriber.onError(new Throwable("網(wǎng)絡(luò)連接超時"));
                       subscriber.onCompleted();
                   }
               }
           });
    }
}

這樣一次基本的Login,通過MVP的調(diào)用就完成了請求到耻煤,展示的過程具壮。
下面我們再來看一下RxJava的簡單解析准颓。
整體來說,RxJava是一個基于觀察者模式的處理異步編程的庫棺妓,它讓代碼的異步操作變得非常簡單攘已,(當(dāng)然還有很多其他方面,先不深究)怜跑。
在LoginModelImpl中样勃,我們看到創(chuàng)建了一個被觀察者Observable,在里面我們調(diào)用了訂閱者subscriber的onNext性芬、onComplete峡眶、onError方法。在這里以登錄為例植锉,當(dāng)正常返回LoginBean的時候辫樱,我們就調(diào)用subscriber的onNext方法,將數(shù)據(jù)傳給訂閱者汽煮;當(dāng)數(shù)據(jù)連接異常的時候搏熄,調(diào)用subscriber的onError方法,將異常傳遞給訂閱者暇赤。
下面我們看一下Observable的觀察訂閱者心例,即LoginPresenterImpl的login方法

 loginModel.login(phone,passWord)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Subscriber<LoginBean>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        if (e!=null)
                       loginView.showLoginResult(e.getMessage());
                    }

                    @Override
                    public void onNext(LoginBean loginBean) {

        }

可以看到在LoginModelImpl中,我們并沒有開啟網(wǎng)絡(luò)請求線程鞋囊, .subscribeOn(Schedulers.io())代表了Observable在子線程止后,而
observeOn(AndroidSchedulers.mainThread())表示在主線程訂閱,可以看到通過非常簡單的兩句話溜腐,就完成了線程的切換译株。subscribe(new Subscriber<LoginBean>() {},這里就是我們的訂閱者挺益,onNext歉糜、onComplete、onError的三個方法望众,就會回調(diào)之前LoginModelImpl中的被訂閱者Observeable匪补。這樣就基本完成了Rxjava的簡單流程。
當(dāng)然烂翰,訂閱記得調(diào)用subscription的解除訂閱夯缺,subscription.unsubscribe();

最后,細(xì)心的觀察會發(fā)現(xiàn)這上面的MVP有可能會產(chǎn)生內(nèi)存泄漏甘耿,我們在訂閱的時候使用了匿名內(nèi)部類踊兜,而匿名內(nèi)部類默認(rèn)持有外部類的引用,而外部類LoginPresenterImpl又持有了LoginActivity.this佳恬,這樣當(dāng)我們的請求很慢捏境,還沒返回?cái)?shù)據(jù)時于游,我們就退出Actiivty,則就會產(chǎn)生資源無法釋放典蝌,導(dǎo)致內(nèi)存泄漏曙砂。這個問題后面再解決了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骏掀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子柱告,更是在濱河造成了極大的恐慌截驮,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件际度,死亡現(xiàn)場離奇詭異葵袭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)乖菱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門坡锡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窒所,你說我怎么就攤上這事鹉勒。” “怎么了吵取?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵禽额,是天一觀的道長。 經(jīng)常有香客問我皮官,道長脯倒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任捺氢,我火速辦了婚禮藻丢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘摄乒。我一直安慰自己悠反,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布缺狠。 她就那樣靜靜地躺著问慎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挤茄。 梳的紋絲不亂的頭發(fā)上如叼,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音穷劈,去河邊找鬼笼恰。 笑死踊沸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的社证。 我是一名探鬼主播逼龟,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼追葡!你這毒婦竟也來了腺律?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤宜肉,失蹤者是張志新(化名)和其女友劉穎匀钧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谬返,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡之斯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了遣铝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佑刷。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酿炸,靈堂內(nèi)的尸體忽然破棺而出瘫絮,到底是詐尸還是另有隱情,我是刑警寧澤梁沧,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布檀何,位于F島的核電站,受9級特大地震影響廷支,放射性物質(zhì)發(fā)生泄漏频鉴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一恋拍、第九天 我趴在偏房一處隱蔽的房頂上張望垛孔。 院中可真熱鬧,春花似錦施敢、人聲如沸周荐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽概作。三九已至,卻和暖如春默怨,著一層夾襖步出監(jiān)牢的瞬間讯榕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留愚屁,地道東北人济竹。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像霎槐,于是被迫代替她去往敵國和親送浊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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