在通過AS開發(fā)Android APP的一個鮮為人知的特性就是使用數(shù)據(jù)綁定(data binding)。通過這種手段,可以實現(xiàn)非常多有用的特性,這些會在我未來的文章中有所介紹,但有一點最最基礎需要你知道的事情就是去掉了findViewById。
是否這些代碼是讓你頭疼的
TextView hello = (TextView) findViewById(R.id.hello);
有很多有用的工具,主要用來消除這些代碼里面類似這樣的代碼。但是在AS 1.5或者更高級的版本中,官方提供了一個方法可以替代上面的操作。
首先你需要修改你的APP的build.gradle文件,在android的代碼塊后,添加下面的語句
android {
…
dataBinding.enabled = true
}
接下來你需要在你的layout文件的最外層添加tag <layout>,用來替代任何你所使用的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>
這個layout標簽用來提示AS在進行下一步之前需要額外的處理,找到一些有趣的Views并且標記他們。所有沒有添加外層layout標簽的的布局是不會經(jīng)歷多余的處理過程,所以你可以在你的程序中不修改其他任何東西的前提下,方便的將其他你喜歡的地方。
你所要做的下一鍵事情就是告訴它在運行時載入不同的布局文件。由于這些工作又回到了Eclaire的release,對于新的架構變化不依賴加載這些預處理的布局文件。因此,你需要修改一下你的加載過程。
對于一個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!
這里你可以看到這樣的一個類,HelloWorldBinding是通過hello_world.xml布局文件和具有ID"@+id/hello"的View去分配的一個你可以使用的final作用域hello。沒有轉換,沒有findViewById。
這種訪問views的機制不但相較于findViewById更加簡單,而且速度也更加快!綁定的過程對于一個布局上的所有Views只需要一次遍歷,就可以注冊對應的作用域。若你使用findViewById,你的view層級需要在每一次的調(diào)用中都去尋找。
還有一件事情,就是你看到的變量名是通過駝峰命名法來的(就像hello_world.xml最后定義為了HelloWorldBinding類),所有你給ID"@+id/hello_text"的命名應該為helloText。
若你將布局文件擴展到RecyclerView,ViewPager,或者其他沒有設置在Activity的內(nèi)容中的地方,你需要在通用的類中使用通用的類型安全的方法調(diào)用。這里有很多適合LayoutInflater的版本,你只需要挑選一個你最喜歡的方式。例如:
HelloWorldBinding binding = HelloWorldBinding.inflate(
getLayoutInflater(), container, attachToContainer);
如果你無法在ViewGroup的容器中去擴展,你需要去擴展View層級。(這一句翻譯的還是有問題)你可以在綁定的時候通過getRoot()得到:
linearLayout.addView(binding.getRoot());
現(xiàn)在,你可能會想,如果我通過一些不同的Views用不同的構造方法但又要使用一個布局時改怎么辦?在布局的預處理和運行時的階段,對于你所綁定的View IDs生成了一個類,只不過是將那些你沒有使用的擴展layout設置為Null。
是不是很神奇?最好玩的部分在于,通過這種方法在運行時沒有使用反射,也沒有使用任何高科技手段。這可以非常簡單的將你目前的APP接入這種方法,這會使得你的工作更加簡單一點,并且還可以使你的layouts加載的更加快一點。
第一次翻譯,有很多地方還不是很規(guī)范,不斷學習吧。