Android 全新MVVM框架搭建

閑話不多少往湿,還是老套路妖异,處理一個(gè)登陸的業(yè)務(wù)。詳細(xì)的介紹MVVM我就不多說(shuō)了领追,網(wǎng)上一大把他膳,畢竟吹水還是我的弱項(xiàng)。
主要實(shí)現(xiàn)的功能有兩個(gè)輸入框绒窑,一個(gè)登陸按鈕棕孙,兩個(gè)TextView顯示登陸結(jié)果。
秀一把我的LoginActivity

@BindLayout(R.layout.activity_login)
public class LoginActivity extends BaseActivity<ILoginViewModel, LoginActivityBriefnessor> implements ILoginView {
    @Override
    protected ILoginViewModel createViewModel(LoginActivityBriefnessor briefnessor) {
        return new LoginViewModel(this, briefnessor);
    }
}

是不是超級(jí)簡(jiǎn)潔些膨,點(diǎn)擊事件呢蟀俊?怎么不見(jiàn)了,再看一看ViewModel

public class LoginViewModel extends BaseViewModel<ILoginView, ILoginModel, LoginActivityBriefnessor> implements ILoginViewModel {

    public LoginViewModel(ILoginView view, LoginActivityBriefnessor briefnessor) {
        super(view, briefnessor);
    }

    @Override
    protected ILoginModel createModel() {
        return new LoginModel(this);
    }

    @Override
    public void onLoginClick(String account, String pswd) {
        if (account.length() < 3) {
            Toast.makeText(context(), "賬號(hào)不正確", Toast.LENGTH_SHORT).show();
            return;
        }
        if (pswd.length() < 3) {
            Toast.makeText(context(), "密碼不正確", Toast.LENGTH_SHORT).show();
            return;
        }
        model.login(account, pswd);
    }

    @Override
    public void callbackLogin(LoginResult result) {
        briefnessor.setResult(result);
    }
}

ViewModel制作了登陸的數(shù)據(jù)驗(yàn)證订雾,以及登陸回調(diào)的實(shí)現(xiàn)肢预,model層完成模擬了登陸。
整個(gè)登陸的業(yè)務(wù)流程Activity并沒(méi)有參與洼哎,在這其中就不得不提一個(gè)關(guān)鍵的中間件Briefness烫映,它連接了View層與Model層,幫我們實(shí)現(xiàn)了數(shù)據(jù)綁定谱净,以及事件傳遞窑邦。
我們先看一看布局是如何實(shí)現(xiàn)的

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:imports="com.hacknife.demo.bean.LoginResult,result"a
    app:viewModel="com.hacknife.demo.mvvm.viewmodel.ILoginViewModel"
    tools:ignore="MissingPrefix">

    <EditText
        android:id="@+id/et_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:hint="賬號(hào)" />

    <EditText
        android:id="@+id/et_pswd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:hint="密碼" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginHorizontal="40dp"
        android:layout_marginVertical="10dp"
        android:text="登陸"
        app:transfer="onLoginClick($et_account$,$et_pswd$)" />

    <LinearLayout style="@style/text_parent" android:layout_marginHorizontal="40dp">

        <TextView
            style="@style/text_childer"
            android:text="返回碼" />

        <TextView
            android:id="@+id/tv_code"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:bind="$result.code$" />
    </LinearLayout>

    <LinearLayout style="@style/text_parent" android:layout_marginHorizontal="40dp">

        <TextView
            style="@style/text_childer"
            android:text="結(jié)果:" />

        <TextView
            android:id="@+id/tv_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:bind="$result.msg$" />
    </LinearLayout>
</LinearLayout>

布局中,根布局綁定了ViewModel壕探,以及用于展示登陸結(jié)果的數(shù)據(jù)源冈钦。登陸按鈕傳遞單擊登陸事件,剩下的兩個(gè)textView綁定相應(yīng)的字段李请。
同時(shí)在對(duì)應(yīng)的Activity上綁定相應(yīng)的布局文件瞧筛,Briefness就能暫時(shí)他強(qiáng)大的功能了,它會(huì)自動(dòng)生成[類(lèi)名+Briefnessor]的類(lèi)导盅。

public class LoginActivityBriefnessor implements Briefnessor<LoginActivity> {
    public EditText et_account;
    public EditText et_pswd;
    public Button btn_login;
    public TextView tv_code;
    public TextView tv_msg;
    public LoginResult result;
    public ILoginViewModel viewModel;

    @Override
    public void bind(final LoginActivity host, Object source) {
        if (!Utils.contentViewExist(host)) {
            host.setContentView(R.layout.activity_login);
        }
        et_account = (EditText) host.findViewById(R.id.et_account);
        et_pswd = (EditText) host.findViewById(R.id.et_pswd);
        btn_login = (Button) host.findViewById(R.id.btn_login);
        tv_code = (TextView) host.findViewById(R.id.tv_code);
        tv_msg = (TextView) host.findViewById(R.id.tv_msg);
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.onLoginClick(et_account.getText().toString().trim() , et_pswd.getText().toString().trim());
            }
        });

    }

    @Override
    public void clear() {
        this.result = null;
        this.viewModel = null;
    }

    @Override
    public void clearAll() {
        this.result = null;
        this.viewModel = null;
        this.et_account = null;
        this.et_pswd = null;
        this.btn_login = null;
        this.tv_code = null;
        this.tv_msg = null;
    }
    @Override
    public void bindViewModel(Object viewModel) {
        this.viewModel = (ILoginViewModel) viewModel;
    }
    public void setResult(LoginResult result) {
        if (result == null) return;
        this.result = result;
        BriefnessInjector.injector(tv_code,result.getCode());
        BriefnessInjector.injector(tv_msg,result.getMsg());
    }
}

該類(lèi)實(shí)現(xiàn)了數(shù)據(jù)綁定较幌,以及向ViewModel發(fā)送消息附帶輸入框中的值。
Briefness的具體用法白翻,請(qǐng)參考https://github.com/hacknife/briefness
下面說(shuō)一說(shuō)BaseActivity

public abstract class BaseActivity<T extends IBaseViewModel,B extends Briefnessor> extends AppCompatActivity implements IBaseView {
    protected T viewModel;
    protected B briefnessor;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        briefnessor = (B )Briefness.bind(this);
        viewModel = createViewModel(briefnessor);
        briefnessor.bindViewModel(viewModel);
        initView();
    }

    protected abstract T createViewModel(B briefnessor);


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (viewModel != null)
            viewModel.dettachView();
    }

    protected void initView() {
    }

    @Override
    public Context applicationContext() {
        return getApplication();
    }

    @Override
    public Activity context() {
        return this;
    }
}

BaseActivity中初始化了Briefness并創(chuàng)建ViewModel綁定到Briefness乍炉,并實(shí)現(xiàn)了IBaseView

public interface IBaseView {

    Context applicationContext();

    Activity context();
}

BaseViewModel繼承AbsViewmodel并實(shí)現(xiàn)IBaseViewModel绢片,持有Briefnessor,View岛琼,Model眷昆。

public abstract class BaseViewModel<V extends IBaseView, M extends IBaseModel, B extends Briefnessor> extends AbsViewModel<V> implements IBaseViewModel {

    protected V view;
    protected M model;
    protected B briefnessor;

    public BaseViewModel(V view, B briefnessor) {
        this.attachView(view);
        this.attachBriefnessor(briefnessor);
        this.view = getView();
        this.briefnessor = (B) getBriefnessor();
        model = createModel();
    }

    protected abstract M createModel();

    @Override
    public Context applicationContext() {
        return view.applicationContext();
    }

    @Override
    public Activity context() {
        return view.context();
    }
}

AbsViewModel 的作用主要是釋放相應(yīng)的連接關(guān)系惕澎。

public abstract class AbsViewModel<T> implements IBaseViewModel{
    protected WeakReference<T> mViewRef;
    protected WeakReference<Briefnessor> mBriefnessorRef;

    protected void attachView(T view) {
        mViewRef = new WeakReference<T>(view);
    }

    protected void attachBriefnessor(Briefnessor briefnessor) {
        mBriefnessorRef = new WeakReference<Briefnessor>(briefnessor);
    }

    protected T getView() {
        return mViewRef.get();
    }

    protected Briefnessor getBriefnessor() {
        return mBriefnessorRef.get();
    }

    public boolean isViewAttached() {
        return mViewRef != null && mViewRef.get() != null & mBriefnessorRef != null & mBriefnessorRef.get() != null;
    }

    public void dettachView() {
        if (mViewRef != null) {
            mViewRef.clear();
            mViewRef = null;
        }
        if (mBriefnessorRef != null) {
            mBriefnessorRef.clear();
            mBriefnessorRef = null;
        }
    }
}

BaseModel 持有ViewModel郑临,并實(shí)現(xiàn)了IBaseView崎页。

public abstract class BaseModel<VM extends IBaseViewModel> implements IBaseModel {
    protected VM viewModel;

    public BaseModel(VM viewModel) {
        this.viewModel = viewModel;
    }

    @Override
    public Context applicationContext() {
        return viewModel.applicationContext();
    }

    @Override
    public Activity context() {
        return viewModel.context();
    }
}

寫(xiě)的不好,請(qǐng)多多見(jiàn)諒困檩,畢竟小學(xué)都沒(méi)畢業(yè)??
如果還有什么不明白的祠挫,代碼直通車(chē)https://github.com/hacknife/Briefness/tree/master/example/src/main/java/com/hacknife/demo/mvvm

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市悼沿,隨后出現(xiàn)的幾起案子等舔,更是在濱河造成了極大的恐慌,老刑警劉巖显沈,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件软瞎,死亡現(xiàn)場(chǎng)離奇詭異逢唤,居然都是意外死亡拉讯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)鳖藕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)魔慷,“玉大人,你說(shuō)我怎么就攤上這事著恩≡憾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵喉誊,是天一觀的道長(zhǎng)邀摆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)伍茄,這世上最難降的妖魔是什么栋盹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮敷矫,結(jié)果婚禮上例获,老公的妹妹穿的比我還像新娘。我一直安慰自己曹仗,他們只是感情好榨汤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著怎茫,像睡著了一般收壕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天蜜宪,我揣著相機(jī)與錄音旬渠,去河邊找鬼。 笑死端壳,一個(gè)胖子當(dāng)著我的面吹牛告丢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播损谦,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岖免,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了照捡?” 一聲冷哼從身側(cè)響起颅湘,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎栗精,沒(méi)想到半個(gè)月后闯参,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悲立,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年鹿寨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薪夕。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脚草,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出原献,到底是詐尸還是另有隱情馏慨,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布姑隅,位于F島的核電站写隶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讲仰。R本人自食惡果不足惜慕趴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叮盘。 院中可真熱鬧秩贰,春花似錦、人聲如沸柔吼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愈魏。三九已至觅玻,卻和暖如春想际,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溪厘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工胡本, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畸悬。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓侧甫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蹋宦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子披粟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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

  • 1、概述 Databinding 是一種框架冷冗,MVVM是一種模式守屉,兩者的概念是不一樣的。我的理解DataBindi...
    Kelin閱讀 76,754評(píng)論 68 521
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,516評(píng)論 25 707
  • 用兩張圖告訴你蒿辙,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料拇泛? 從這篇文章中你...
    hw1212閱讀 12,693評(píng)論 2 59
  • 我們總是無(wú)端的陷入黑暗深淵,但是思灌,終有一天會(huì)有人為你進(jìn)入深淵俺叭,為你清除一切孤獨(dú),害怕的惡魔习瑰。 熱烈的陽(yáng)光透過(guò)濃密的...
    桑小隅閱讀 2,304評(píng)論 0 3
  • 名:劉小瓊 公司:寧波大發(fā)化纖有限公司 寧波盛和塾《六項(xiàng)精進(jìn)》第235期學(xué)員 【日精進(jìn)打卡第30天】 知~學(xué)習(xí) 誦...
    劉小瓊123閱讀 110評(píng)論 0 0