2辫塌、快速上手【最火開(kāi)源框架MVVMHabit簡(jiǎn)單集成】

最火開(kāi)源框架MVVMhabit
一. 準(zhǔn)備工作
二. 快速上手

三. 數(shù)據(jù)綁定

  1. TextView綁定
  2. onClick綁定
  3. ImageView綁定
  4. ListView綁定
  5. RecyclerView綁定

四. 其他

  1. toolbar頭部標(biāo)題
  2. 底部tabBar第三方按鈕

2.1回论、第一個(gè)Activity

以大家都熟悉的登錄操作為例:三個(gè)文件LoginActivty.java振诬、LoginViewModel.java椭员、activity_login.xml

2.1.1露乏、關(guān)聯(lián)ViewModel

在activity_login.xml中關(guān)聯(lián)LoginViewModel碧浊。

<layout>
    <data>
        <variable
            type="com.goldze.mvvmhabit.ui.login.LoginViewModel"
            name="viewModel"
        />
    </data>
    .....

</layout>

variable - type:類的全路徑
variable - name:變量名

2.1.2、繼承BaseActivity

LoginActivity繼承BaseActivity

public class LoginActivity extends BaseActivity<ActivityLoginBinding, LoginViewModel> {
    //ActivityLoginBinding類是databinding框架自定生成的,對(duì)activity_login.xml
    @Override
    public int initContentView(Bundle savedInstanceState) {
        return R.layout.activity_login;
    }

    @Override
    public int initVariableId() {
        return BR.viewModel;
    }

    @Override
    public LoginViewModel initViewModel() {
        //View持有ViewModel的引用瘟仿,如果沒(méi)有特殊業(yè)務(wù)處理辉词,這個(gè)方法可以不重寫
        return ViewModelProviders.of(this).get(LoginViewModel.class);
    }
}

保存activity_login.xml后databinding會(huì)生成一個(gè)ActivityLoginBinding類。(如果沒(méi)有生成猾骡,試著點(diǎn)擊Build->Clean Project)

BaseActivity是一個(gè)抽象類瑞躺,有兩個(gè)泛型參數(shù),一個(gè)是ViewDataBinding兴想,另一個(gè)是BaseViewModel幢哨,上面的ActivityLoginBinding則是繼承的ViewDataBinding作為第一個(gè)泛型約束,LoginViewModel繼承BaseViewModel作為第二個(gè)泛型約束嫂便。

重寫B(tài)aseActivity的二個(gè)抽象方法

initContentView() 返回界面layout的id
initVariableId() 返回變量的id捞镰,對(duì)應(yīng)activity_login中name="viewModel",就像一個(gè)控件的id,可以使用R.id.xxx岸售,這里的BR跟R文件一樣践樱,由系統(tǒng)生成,使用BR.xxx找到這個(gè)ViewModel的id凸丸。

選擇性重寫initViewModel()方法拷邢,返回ViewModel對(duì)象

@Override
public LoginViewModel initViewModel() {
    //View持有ViewModel的引用,如果沒(méi)有特殊業(yè)務(wù)處理屎慢,這個(gè)方法可以不重寫
    return ViewModelProviders.of(this).get(LoginViewModel.class);
}

注意: 不重寫initViewModel()瞭稼,默認(rèn)會(huì)創(chuàng)建LoginActivity中第二個(gè)泛型約束的LoginViewModel,如果沒(méi)有指定第二個(gè)泛型腻惠,則會(huì)創(chuàng)建BaseViewModel

2.1.3环肘、繼承BaseViewModel

LoginViewModel繼承BaseViewModel

public class LoginViewModel extends BaseViewModel {
    public LoginViewModel(@NonNull Application application) {
        super(application);
    }
    ....
}

BaseViewModel與BaseActivity通過(guò)LiveData來(lái)處理常用UI邏輯,即可在ViewModel中使用父類的showDialog()集灌、startActivity()等方法悔雹。在這個(gè)LoginViewModel中就可以盡情的寫你的邏輯了!

BaseFragment的使用和BaseActivity一樣欣喧,詳情參考Demo荠商。

2.2、數(shù)據(jù)綁定

擁有databinding框架自帶的雙向綁定续誉,也有擴(kuò)展

2.2.1莱没、傳統(tǒng)綁定

綁定用戶名:

在LoginViewModel中定義

//用戶名的綁定
public ObservableField<String> userName = new ObservableField<>("");

在用戶名EditText標(biāo)簽中綁定

android:text="@={viewModel.userName}"

這樣一來(lái),輸入框中輸入了什么酷鸦,userName.get()的內(nèi)容就是什么饰躲,userName.set("")設(shè)置什么,輸入框中就顯示什么臼隔。 注意: @符號(hào)后面需要加=號(hào)才能達(dá)到雙向綁定效果嘹裂;userName需要是public的,不然viewModel無(wú)法找到它摔握。

點(diǎn)擊事件綁定:

在LoginViewModel中定義

//登錄按鈕的點(diǎn)擊事件
public View.OnClickListener loginOnClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {

    }
};

在登錄按鈕標(biāo)簽中綁定

android:onClick="@{viewModel.loginOnClick}"

這樣一來(lái)寄狼,用戶的點(diǎn)擊事件直接被回調(diào)到ViewModel層了,更好的維護(hù)了業(yè)務(wù)邏輯

這就是強(qiáng)大的databinding框架雙向綁定的特性氨淌,不用再給控件定義id泊愧,setText(),setOnClickListener()盛正。

但是删咱,光有這些,完全滿足不了我們復(fù)雜業(yè)務(wù)的需求昂荔荨痰滋!MVVMHabit閃亮登場(chǎng):它有一套自定義的綁定規(guī)則摘能,可以滿足大部分的場(chǎng)景需求,請(qǐng)繼續(xù)往下看敲街。

2.2.2团搞、自定義綁定

還拿點(diǎn)擊事件說(shuō)吧,不用傳統(tǒng)的綁定方式多艇,使用自定義的點(diǎn)擊事件綁定逻恐。

在LoginViewModel中定義

//登錄按鈕的點(diǎn)擊事件
public BindingCommand loginOnClickCommand = new BindingCommand(new BindingAction() {
    @Override
    public void call() {

    }
});

在activity_login中定義命名空間

xmlns:binding="http://schemas.android.com/apk/res-auto"

在登錄按鈕標(biāo)簽中綁定

binding:onClickCommand="@{viewModel.loginOnClickCommand}"

這和原本傳統(tǒng)的綁定不是一樣嗎?不墩蔓,這其實(shí)是有差別的梢莽。使用這種形式的綁定萧豆,在原本事件綁定的基礎(chǔ)之上奸披,帶有防重復(fù)點(diǎn)擊的功能,1秒內(nèi)多次點(diǎn)擊也只會(huì)執(zhí)行一次操作涮雷。如果不需要防重復(fù)點(diǎn)擊阵面,可以加入這條屬性

binding:isThrottleFirst="@{Boolean.TRUE}"

那這功能是在哪里做的呢?答案在下面的代碼中洪鸭。

//防重復(fù)點(diǎn)擊間隔(秒)
public static final int CLICK_INTERVAL = 1;

/**
* requireAll 是意思是是否需要綁定全部參數(shù), false為否
* View的onClick事件綁定
* onClickCommand 綁定的命令,
* isThrottleFirst 是否開(kāi)啟防止過(guò)快點(diǎn)擊
*/
@BindingAdapter(value = {"onClickCommand", "isThrottleFirst"}, requireAll = false)
public static void onClickCommand(View view, final BindingCommand clickCommand, final boolean isThrottleFirst) {
    if (isThrottleFirst) {
        RxView.clicks(view)
        .subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object object) throws Exception {
                if (clickCommand != null) {
                    clickCommand.execute();
                }
            }
        });
    } else {
        RxView.clicks(view)
        .throttleFirst(CLICK_INTERVAL, TimeUnit.SECONDS)//1秒鐘內(nèi)只允許點(diǎn)擊1次
        .subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object object) throws Exception {
                if (clickCommand != null) {
                    clickCommand.execute();
                }
            }
        });
    }
}

onClickCommand方法是自定義的样刷,使用@BindingAdapter注解來(lái)標(biāo)明這是一個(gè)綁定方法。在方法中使用了RxView來(lái)增強(qiáng)view的clicks事件览爵,.throttleFirst()限制訂閱者在指定的時(shí)間內(nèi)重復(fù)執(zhí)行置鼻,最后通過(guò)BindingCommand將事件回調(diào)出去,就好比有一種攔截器蜓竹,在點(diǎn)擊時(shí)先做一下判斷箕母,然后再把事件沿著他原有的方向傳遞。

是不是覺(jué)得有點(diǎn)意思俱济,好戲還在后頭呢嘶是!

2.2.3、自定義ImageView圖片加載

綁定圖片路徑:

在ViewModel中定義

public String imgUrl = "http://img0.imgtn.bdimg.com/it/u=2183314203,562241301&fm=26&gp=0.jpg";

在ImageView標(biāo)簽中

binding:url="@{viewModel.imgUrl}"

url是圖片路徑蛛碌,這樣綁定后聂喇,這個(gè)ImageView就會(huì)去顯示這張圖片,不限網(wǎng)絡(luò)圖片還是本地圖片蔚携。


如果需要給一個(gè)默認(rèn)加載中的圖片希太,可以加這一句

binding:placeholderRes="@{R.mipmap.ic_launcher_round}"

R文件需要在data標(biāo)簽中導(dǎo)入使用,如:<import type="com.goldze.mvvmhabit.R" />

BindingAdapter中的實(shí)現(xiàn):創(chuàng)建自定義文件ViewAdapter.java寫入下面代碼實(shí)現(xiàn)BindingAdapter

@BindingAdapter(value = {"url", "placeholderRes"}, requireAll = false)
public static void setImageUri(ImageView imageView, String url, int placeholderRes) {
    if (!TextUtils.isEmpty(url)) {
        //使用Glide框架加載圖片
        Glide.with(imageView.getContext())
                .load(url)
                .apply(new RequestOptions().placeholder(placeholderRes))
                .into(imageView);
    }
}

很簡(jiǎn)單就自定義了一個(gè)ImageView圖片加載的綁定酝蜒,學(xué)會(huì)這種方式跛十,可自定義擴(kuò)展。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秕硝,一起剝皮案震驚了整個(gè)濱河市芥映,隨后出現(xiàn)的幾起案子洲尊,更是在濱河造成了極大的恐慌,老刑警劉巖奈偏,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坞嘀,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惊来,警方通過(guò)查閱死者的電腦和手機(jī)丽涩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)裁蚁,“玉大人矢渊,你說(shuō)我怎么就攤上這事⊥髦ぃ” “怎么了矮男?”我有些...
    開(kāi)封第一講書人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)室谚。 經(jīng)常有香客問(wèn)我毡鉴,道長(zhǎng),這世上最難降的妖魔是什么秒赤? 我笑而不...
    開(kāi)封第一講書人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任猪瞬,我火速辦了婚禮,結(jié)果婚禮上入篮,老公的妹妹穿的比我還像新娘陈瘦。我一直安慰自己,他們只是感情好潮售,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布痊项。 她就那樣靜靜地躺著,像睡著了一般饲做。 火紅的嫁衣襯著肌膚如雪线婚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,184評(píng)論 1 308
  • 那天盆均,我揣著相機(jī)與錄音塞弊,去河邊找鬼。 笑死泪姨,一個(gè)胖子當(dāng)著我的面吹牛游沿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肮砾,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诀黍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了仗处?” 一聲冷哼從身側(cè)響起眯勾,我...
    開(kāi)封第一講書人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤枣宫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吃环,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體也颤,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年郁轻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了翅娶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡好唯,死狀恐怖竭沫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布卦洽,位于F島的核電站,受9級(jí)特大地震影響贯溅,放射性物質(zhì)發(fā)生泄漏拄氯。R本人自食惡果不足惜躲查,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望译柏。 院中可真熱鬧镣煮,春花似錦、人聲如沸鄙麦。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胯府。三九已至介衔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骂因,已是汗流浹背炎咖。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寒波,地道東北人乘盼。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像俄烁,于是被迫代替她去往敵國(guó)和親绸栅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359

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