在通過(guò)AS開(kāi)發(fā)Android APP的一個(gè)鮮為人知的特性就是使用數(shù)據(jù)綁定(data binding)。通過(guò)這種手段伶棒,可以實(shí)現(xiàn)非常多有用的特性钩述,這些會(huì)在我未來(lái)的文章中有所介紹,但有一點(diǎn)最最基礎(chǔ)需要你知道的事情就是去掉了findViewById宛裕。
是否這些代碼是讓你頭疼的
TextView hello = (TextView) findViewById(R.id.hello);
有很多有用的工具瑟啃,主要用來(lái)消除這些代碼里面類(lèi)似這樣的代碼。但是在AS 1.5或者更高級(jí)的版本中揩尸,官方提供了一個(gè)方法可以替代上面的操作蛹屿。
首先你需要修改你的APP的build.gradle文件,在android的代碼塊后,添加下面的語(yǔ)句
android {
…
dataBinding.enabled = true
}
接下來(lái)你需要在你的layout文件的最外層添加tag <layout>赖条,用來(lái)替代任何你所使用的ViewGroup:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</layout>
這個(gè)layout標(biāo)簽用來(lái)提示AS在進(jìn)行下一步之前需要額外的處理,找到一些有趣的Views并且標(biāo)記他們褂策。所有沒(méi)有添加外層layout標(biāo)簽的的布局是不會(huì)經(jīng)歷多余的處理過(guò)程犹撒,所以你可以在你的程序中不修改其他任何東西的前提下折联,方便的將其他你喜歡的地方。
你所要做的下一鍵事情就是告訴它在運(yùn)行時(shí)載入不同的布局文件识颊。由于這些工作又回到了Eclaire的release诚镰,對(duì)于新的架構(gòu)變化不依賴(lài)加載這些預(yù)處理的布局文件。因此祥款,你需要修改一下你的加載過(guò)程清笨。
對(duì)于一個(gè)Activity,替換之前的:
setContentView(R.layout.hello_world);
TextView hello = (TextView) findViewById(R.id.hello);
hello.setText("Hello World"); // for example, but you'd use
// resources, right?
你可以這樣的去加載它:
HelloWorldBinding binding =
DataBindingUtil.setContentView(this, R.layout.hello_world);
binding.hello.setText("Hello World"); // you should use resources!
這里你可以看到這樣的一個(gè)類(lèi)刃跛,HelloWorldBinding是通過(guò)hello_world.xml布局文件和具有ID"@+id/hello"的View去分配的一個(gè)你可以使用的final作用域hello抠艾。沒(méi)有轉(zhuǎn)換,沒(méi)有findViewById桨昙。
這種訪(fǎng)問(wèn)views的機(jī)制不但相較于findViewById更加簡(jiǎn)單检号,而且速度也更加快!綁定的過(guò)程對(duì)于一個(gè)布局上的所有Views只需要一次遍歷绊率,就可以注冊(cè)對(duì)應(yīng)的作用域谨敛。若你使用findViewById,你的view層級(jí)需要在每一次的調(diào)用中都去尋找滤否。
還有一件事情脸狸,就是你看到的變量名是通過(guò)駝峰命名法來(lái)的(就像hello_world.xml最后定義為了HelloWorldBinding類(lèi)),所有你給ID"@+id/hello_text"的命名應(yīng)該為helloText藐俺。
若你將布局文件擴(kuò)展到RecyclerView炊甲,ViewPager,或者其他沒(méi)有設(shè)置在Activity的內(nèi)容中的地方欲芹,你需要在通用的類(lèi)中使用通用的類(lèi)型安全的方法調(diào)用卿啡。這里有很多適合LayoutInflater的版本,你只需要挑選一個(gè)你最喜歡的方式菱父。例如:
HelloWorldBinding binding = HelloWorldBinding.inflate(
getLayoutInflater(), container, attachToContainer);
如果你無(wú)法在ViewGroup的容器中去擴(kuò)展颈娜,你需要去擴(kuò)展View層級(jí)。(這一句翻譯的還是有問(wèn)題)你可以在綁定的時(shí)候通過(guò)getRoot()得到:
linearLayout.addView(binding.getRoot());
現(xiàn)在浙宜,你可能會(huì)想官辽,如果我通過(guò)一些不同的Views用不同的構(gòu)造方法但又要使用一個(gè)布局時(shí)改怎么辦?在布局的預(yù)處理和運(yùn)行時(shí)的階段粟瞬,對(duì)于你所綁定的View IDs生成了一個(gè)類(lèi)同仆,只不過(guò)是將那些你沒(méi)有使用的擴(kuò)展layout設(shè)置為Null。
是不是很神奇裙品?最好玩的部分在于俗批,通過(guò)這種方法在運(yùn)行時(shí)沒(méi)有使用反射俗或,也沒(méi)有使用任何高科技手段。這可以非常簡(jiǎn)單的將你目前的APP接入這種方法岁忘,這會(huì)使得你的工作更加簡(jiǎn)單一點(diǎn)辛慰,并且還可以使你的layouts加載的更加快一點(diǎn)。
第一次翻譯干像,有很多地方還不是很規(guī)范昆雀,不斷學(xué)習(xí)吧。