Android MVP框架

關(guān)于mvp框架的使用赡矢,已經(jīng)有很多文章記介紹了杭朱。MVP的概念就不再闡述,本文純屬記錄下自己的使用心得吹散,方便后續(xù)自己查看弧械。

image.png

如上圖所示,有四個關(guān)鍵字空民,分別是:Contract刃唐、IBaseView羞迷、IBaseModel、BasePresenter画饥。
正如圖中所介紹的衔瓮,Contract是M、V抖甘、P的契約热鞍。Contract是Interface,每一組mvp行為對應(yīng)一個Contract衔彻。每一個Contract 包含3個interface薇宠,分別是M、V艰额、P澄港。結(jié)合??代碼方便理解Contract。

(登錄案例)

public interface LoginContract {


    interface Model extends IBaseModel {
        /**
         * 統(tǒng)一登錄接口
         * @param userName  用戶名
         * @param password  密碼
         * @param authType  認(rèn)證類型:1-默認(rèn)  4-手勢密碼
         * @param callback  回調(diào)
         */
        void login(String userName, String password,String authType,ResponseCallback<LoginBean> callback);
    }

    interface View extends IBaseView {
        void loginSuccess(String token);
    }

    interface Presenter {
        void login(String userName,String password,String authType);
    }


}

梳理流程:
點(diǎn)擊登錄按鈕柄沮,調(diào)用LoginContract.Presenter#login方法。在login方法的實(shí)現(xiàn)中漂辐,調(diào)用LoginContract.Model#login棕硫,并通過回調(diào)的方式(ResponseCallback)返回結(jié)果髓涯,并在回調(diào)函數(shù)中執(zhí)行視圖操作LoginContract.View#loginSuccess哈扮。

??ResponseCallback

public interface ResponseCallback<T> {

    void success(T response);

    void fail(String s);

    void error(String error);

}

Contract中的M和P需要自定義對應(yīng)的類,V需要在對應(yīng)的Activity implements滑肉。
??Model:implements LoginContract.Model包各,重寫login方法问畅,并回調(diào)返回結(jié)果护姆。

public class LoginModel implements LoginContract.Model {

    @Override
    public void login(String userName, String password, String authType,ResponseCallback<LoginBean> callback) {
        ...
        PlatformService service = RetrofitClientMptl.getService(PlatformService.class);
        Call<LoginBean> call = service.lockLogin(body);
        Cutscenes.show(null,null,false,false);
        call.enqueue(new Callback<LoginBean>() {
            @Override
            public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
                if (response.isSuccessful()){
                    callback.success(response.body());
                } else {
                    //TODO
                    callback.error("網(wǎng)絡(luò)通信異常掏击,請重試");
                }
            }

            @Override
            public void onFailure(Call<LoginBean> call, Throwable t) {
                t.printStackTrace();
                callback.fail(t.getMessage());
            }
        });

    }
}

??Presenter:繼承BasePresenter灯变,implements LoginContract.Presenter。重寫login滚粟、createModule方法坦刀。login方法中調(diào)用Model的login,并在定義的回調(diào)函數(shù)中林艘,調(diào)用View的loginSuccess方法混坞。

public class LoginPresenter extends BasePresenter<LoginContract.Model,LoginContract.View>
        implements LoginContract.Presenter {
    @Override
    public void login(String userName,String password,String authType) {
        if(isViewAttached()){
            getView().showLoading();
            getModule().login(userName, password, authType, new ResponseCallback<LoginBean>() {
                @Override
                public void success(LoginBean response) {
                    getView().dismissLoading();
                    if(response.getError() == null){
                        getView().loginSuccess(response.getAccess_token());
                    } else if(response.getError().equals("invalid_grant")){
                        toast("用戶名或密碼錯誤");
                    } else if(response.getError().equals("unauthorized")){
                        toast("用戶未開通登錄權(quán)限");
                    } else {
                        toast("登錄失敗");
                    }
                }

                @Override
                public void fail(String s) {
                    toast(s);
                    getView().dismissLoading();
                }

                @Override
                public void error(String error) {
                    toast(error);
                    getView().dismissLoading();
                }
            });
        }
    }

    @Override
    protected LoginContract.Model createModule() {
        return new LoginModel();
    }

    @Override
    public void start() {

    }
}

??剩下的View呢

public class LoginActivity extends BaseMVPActivity<LoginPresenter> 
                           implements LoginContract.View {

    @Override
    protected void initPresenter() {
        mPresenter = new LoginPresenter();
    }
    ??????//點(diǎn)擊登錄事件
    public void login(View view) {
        mPresenter.login(userName, password, "1");
    }
    ??????
    @Override
    public void loginSuccess(String token) {
        startActivity(new Intent(LoginActivity.this, HomeActivity.class));
        finish();
    }
}

??MVP的基類和BaseMVPActivity基類:??

IBaseModel

public interface IBaseModel {
}

IBaseView

public interface IBaseView {

    /**
     * 顯示加載框
     */
    void showLoading();

    /**
     * 隱藏加載框
     */
    void dismissLoading();

    void toast(String msg);

    /**
     * 上下文
     *
     * @return context
     */
    Context getContext();
}

BasePresenter

public abstract class BasePresenter<M extends IBaseModel, V extends IBaseView> {

    private WeakReference<V> mvpView;
    private M mvpModel;

    /**
     * 綁定View
     */
    @SuppressWarnings("unchecked")
    public void attachView(V view) {
        mvpView = new WeakReference<>(view);
        if (mvpModel == null) {
            mvpModel = createModule();
        }
    }

    /**
     * 解綁View
     */
    public void detachView() {
        if (null != mvpView) {
            mvpView.clear();
            mvpView = null;
        }
        this.mvpModel = null;
    }

    /**
     * 是否與View建立連接
     */
    protected boolean isViewAttached() {
        return null != mvpView && null != mvpView.get();
    }

    protected V getView() {
        return isViewAttached() ? mvpView.get() : null;
    }

    protected M getModule() {
        return mvpModel;
    }

    protected Context getContext() {
        return getView().getContext();
    }

    protected void showLoading() {
        getView().showLoading();
    }

    protected void dismissLoading() {
        getView().dismissLoading();
    }

    protected void toast(String s) {
        getView().toast(s);
    }


    /**
     * 通過該方法創(chuàng)建Module
     */
    protected abstract M createModule();

    /**
     * 初始化方法
     */
    public abstract void start();


}

BaseMVPActivity

public abstract class BaseMVPActivity<P extends BasePresenter> extends AppCompatActivity implements IBaseView {

    protected P mPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(initLayout());
        ActivityUtil.push(this);
        //初始化mPresenter
        initPresenter();

        //綁定view
        if(mPresenter != null){
            mPresenter.attachView(this);
        }
        //初始化
        initView();
        initData();
    }

    protected abstract void initData();

    /**
     * 初始化mPresenter
     */
    protected abstract void initPresenter();

    /**
     * 初始化
     */
    protected abstract void initView();

    /**
     * 獲取布局id
     * @return
     */
    protected abstract int initLayout();


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mPresenter != null){
            mPresenter.detachView();
            mPresenter = null;
        }
        ActivityUtil.remove(this);
    }


    @Override
    public void toast(String msg) {
        Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showLoading() {
        Cutscenes.show(null,null,false,false);
    }

    @Override
    public void dismissLoading() {
        Cutscenes.dismiss(true);
    }

    @Override
    public Context getContext() {
        return this;
    }


}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厨诸,一起剝皮案震驚了整個濱河市微酬,隨后出現(xiàn)的幾起案子颗管,更是在濱河造成了極大的恐慌垦江,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異项秉,居然都是意外死亡慷彤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哗蜈,“玉大人坠韩,你說我怎么就攤上這事只搁∏馔铮” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長来屠。 經(jīng)常有香客問我秫舌,道長足陨,這世上最難降的妖魔是什么墨缘? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任镊讼,我火速辦了婚禮蝶棋,結(jié)果婚禮上玩裙,老公的妹妹穿的比我還像新娘段直。我一直安慰自己鸯檬,他們只是感情好喧务,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布功茴。 她就那樣靜靜地躺著揩懒,像睡著了一般纫溃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旭等,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天衡载,我揣著相機(jī)與錄音,去河邊找鬼弃榨。 笑死,一個胖子當(dāng)著我的面吹牛鲸睛,可吹牛的內(nèi)容都是我干的坡贺。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼拳亿,長吁一口氣:“原來是場噩夢啊……” “哼愿伴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隔节,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞬雹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呢诬,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胖缤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狗唉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涡真。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哆料,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杏节,我是刑警寧澤典阵,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站壮啊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏充坑。R本人自食惡果不足惜染突,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望也榄。 院中可真熱鬧,春花似錦甜紫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽额嘿。三九已至劣挫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間球拦,已是汗流浹背帐我。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拦键,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像碳柱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子莲镣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

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