寫在前面
在以往的android開發(fā)中蜡励,我們需要使用到findviewById方法來進(jìn)行初始化view,所以對(duì)于頁面復(fù)雜的情況嗦篱,經(jīng)常會(huì)看到十幾二十行的findviewById方法,而如果需要設(shè)置點(diǎn)擊事件,則又需要十幾二十行的代碼损晤,寫著很枯燥也很耽擱時(shí)間。作為一個(gè)程序員而不是搬運(yùn)工红竭,千萬不要做沒有效率的事尤勋,好在jake大神給我們帶來了ButterKnife,在一段時(shí)間內(nèi)為我們自動(dòng)綁定了view茵宪,代替了繁雜的手寫步驟最冰。
可是相信使用過ButterKnife的同學(xué)都有一個(gè)感受,就是如果一個(gè)頁面view過多的話稀火,也需要一長(zhǎng)串的bindView代碼暖哨,導(dǎo)致一個(gè)頁面輕輕松松300行+的代碼量,看著也有點(diǎn)不舒服凰狞。而這些也都是重復(fù)性的工作篇裁,那么有什么辦法解決嗎?
有胺颉茴恰!
DataBinding
說實(shí)話,DataBinding也出來蠻久了斩熊,可是用的人也蠻少的往枣。原因可能是大家在選擇的時(shí)候多選擇了比較流行的MVP,二來是DataBinding還沒有像前端那樣完善粉渠,處于一個(gè)觀望的狀態(tài)分冈。但是最近已經(jīng)出現(xiàn)了越來越多的DataBinding的文章,說明越來越多的開發(fā)者開始注重這一塊的技術(shù)霸株,畢竟是金子總會(huì)發(fā)光的雕沉,不多說。
首先去件,我們需要開啟DataBinding坡椒,不需要引入額外的依賴庫,因?yàn)镈ataBinding是在support包中的尤溜。
android {
…
dataBinding {
enabled = true
}
}
然后倔叼,我們只需要在改變一下xml的寫法:
//activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
</data>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ditclear.app.MainActivity">
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!"/>
</RelativeLayout>
</layout>
其實(shí)和以前差不多,就是外面包了一層<layout>宫莱,所以遷移起來很快丈攒。
然后就可以使用了,這樣寫了之后,系統(tǒng)會(huì)給你生成一個(gè)以xml文件名為前綴的文件巡验。比如activity_main.xml际插,則會(huì)在build文件夾下生成ActivityMainBinding.java的文件,里面有各種綁定View的操作显设,這樣我們就不用在自己的activity中寫了框弛。而使用的話直接使用ActivityMainBinding的對(duì)象就好了。
例子:
package com.ditclear.app;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import com.ditclear.app.databinding.ActivityMainBinding;//生成的bind文件
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding mBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding= DataBindingUtil.setContentView(this,R.layout.activity_main);
mBinding.contentTv.setText("this is bindText");//輕輕松松拿到view
}
}
很簡(jiǎn)單敷硅,而且activity瞬間簡(jiǎn)潔了功咒。
當(dāng)然還有更簡(jiǎn)單的寫法,生成的binding文件和DataBindingUtil.setContentView()方法其實(shí)都是固定的绞蹦,我們可以使用泛型來簡(jiǎn)化這些步驟力奋,相信大家都想到了。
首先抽象出一個(gè)基類BaseBindActivity:
**
* 頁面描述:activity基類
* <p>
* Created by ditclear on 2017/4/16.
*/
public abstract class BaseBindActivity<VB extends ViewDataBinding> extends AppCompatActivity {
protected VB mBinding;
...
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View rootView = getLayoutInflater().inflate(this.getLayoutId(), null, false);
mBinding = DataBindingUtil.bind(rootView);
super.setContentView(rootView);
...
initView();
}
@LayoutRes
protected abstract int getLayoutId();
protected void initView();
}
接下來幽七,我們繼承它然后傳入layoutId就行了景殷。
package com.ditclear.app;
import com.ditclear.app.base.BaseBindActivity;
import com.ditclear.app.databinding.ActivityMainBinding;
public class MainActivity extends BaseBindActivity<ActivityMainBinding> {
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initView() {
mBinding.contentTv.setText("this is bindText");
}
}
需要注意的是,如果是以include的方式存在于xml文件中的話澡屡,我們需要為include的布局設(shè)置一個(gè)id猿挚,并且include的布局也需要寫成databinding的形式。
toolbar_default.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
</data>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@color/colorPrimary"
app:theme="@style/AppTheme">
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:textColor="@color/text_default"
android:textSize="@dimen/text_size_default"
android:textStyle="bold"/>
</android.support.v7.widget.Toolbar>
</layout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
</data>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ditclear.app.MainActivity">
<include
android:id="@+id/toolbar_layout"
layout="@layout/toolbar_default"/>
<TextView
android:id="@+id/content_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!"/>
</RelativeLayout>
</layout>
這樣我們就能直接操作toolbar了
@Override
protected void initView() {
mBinding.toolbarLayout.titleTv.setText("main");
mBinding.contentTv.setText("this is bindText");
}
當(dāng)然驶鹉,由于有一些子類的布局并不需要include一個(gè)toolbar布局绩蜻,所以在BaseBindActivity里我們還是通過findViewById來進(jìn)行操作,畢竟不能忘本啊室埋。
/**
* 初始化toolbar
*/
private void initToolBar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
//有些布局可能不需要toolbar,判斷是否為空办绝,來進(jìn)行剩下的操作
//recyclerView和RefreshLayout同理
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(null);
setShowBackNavigation(true);
}
}
這樣我們就能操作toolbar了,和以前的寫法一模一樣姚淆,限制就是統(tǒng)一了toolbar的id為toolbar孕蝉,但是我覺得這也能算是團(tuán)隊(duì)間的規(guī)范吧,免得出現(xiàn)形形色色的名稱腌逢。
recyclerView和RefreshLayout同理降淮。
效果
最后
這只是最基礎(chǔ)的綁定view的例子以及使用泛型和DataBinding來構(gòu)造我們的基類,只是寫了一個(gè)BaseActivity搏讶,F(xiàn)ragment同樣的道理佳鳖。DataBinding當(dāng)然不止這些,還能簡(jiǎn)化RecyclerView的操作媒惕,告別反復(fù)的自定義Adapter系吩,推薦大帥的DataBingding入門指南和用于綁定的RecyclerView的庫DataBindingAdapter。
項(xiàng)目地址:https://github.com/ditclear/BaseViewBinding