不要再使用findViewById

在通過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ī)范,不斷學習吧。

原始文章地址

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,383評論 0 17
  • 這是谷歌官方給我們提供的一個兼容低版本安卓設備的軟件包,里面包囊了只有在安卓3.0以上可以使用的api。而view...
    Ten_Minutes閱讀 5,854評論 1 19
  • Day1: 在代碼中通過R.string.hello_world可以獲得該字符串的引用; 在XML中通過@stri...
    冰凝雪國閱讀 1,652評論 0 5
  • 有雨 東風7米/秒 我開早會(簡短的幾句話:要和正能量的人多交流)因為要拍集體照 所以特意洗了頭發(fā)。果然集體照就是...
    綠豆餅餅閱讀 251評論 0 0

友情鏈接更多精彩內(nèi)容