Data-Binding(一):别在使用FindViewById()了
是否这些代码是让你头疼的
TextView hello = (TextView) findViewById(R.id.hello);
有很多有用的工具,主要用来消除这些代码里面类似这样的代码。但是在AS 1.5或者更高级的版本中,官方提供了一个方法可以替代上面的操作。
首先你需要修改你的APP的build.gradle文件,在android的代码块后,添加下面的语句
android {
…
dataBinding.enabled = true
}
接下来你需要在你的layout文件的最外层添加tag
<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标签的的布局是不会经历多余的处理过程,所以你可以在你的程序中不修改其他任何东西的前提下,方便的将其他你喜欢的地方。
你所要做的下一键事情就是告诉它在运行时载入不同的布局文件。由于这些工作又回到了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层级需要在每一次的调用中都去寻找。
还有一件事情,就是你看到的变量名是通过驼峰命名法来的(就像hello_world.xml最后定义为了HelloWorldBinding类),所有你给ID"@+id/hello_text"的命名应该为helloText。
若你将布局文件扩展到RecyclerView,ViewPager,或者其他没有设置在Activity的内容中的地方,你需要在通用的类中使用通用的类型安全的方法调用。这里有很多适合LayoutInflater的版本,你只需要挑选一个你最喜欢的方式。例如:
HelloWorldBinding binding = HelloWorldBinding.inflate(
getLayoutInflater(), container, attachToContainer);
如果你无法在ViewGroup的容器中去扩展,你需要去扩展View层级。(这一句翻译的还是有问题)你可以在绑定的时候通过getRoot()得到:
linearLayout.addView(binding.getRoot());
现在,你可能会想,如果我通过一些不同的Views用不同的构造方法但又要使用一个布局时改怎么办?在布局的预处理和运行时的阶段,对于你所绑定的View IDs生成了一个类,只不过是将那些你没有使用的扩展layout设置为Null。
是不是很神奇?最好玩的部分在于,通过这种方法在运行时没有使用反射,也没有使用任何高科技手段。这可以非常简单的将你目前的APP接入这种方法,这会使得你的工作更加简单一点,并且还可以使你的layouts加载的更加快一点。
第一次翻译,有很多地方还不是很规范,不断学习吧。
历史文章记录: