和在C/C++中直接#include相似,Android在XML布局中支持
(1) 你期望多次使用同样的布局
(2) 你的布局有个通用部分,依赖于设备配置(比如,屏幕方向:landscapte或者protrait)
Listing 8-7给出了当覆盖某些included的布局的属性的时候,如何多次包含一个布局。
Listing 8-7 多次包含布局
如Listing 8-8所展示的,当布局被inflated的时候,布局的包含是动态的。包含应该在编译的时候完成,否则Android不知道include哪个布局(layout-land/mylayout.xml或者layout-port/mylayout.xml)。这和在C/C++中直接#include不同,C/C++被预处理器在编译时候处理。
就像我们在第一章看到的,懒汉式初始化是延迟初始化、提升性能、潜在的节省内存(当对象从来不会被创建)的方便的技术。
Android为了这个目的定义了ViewStub类。ViewStub是一个轻量级的不可见的View,可以用在你的布局中,允许懒汉式当你需要的时候inflate布局资源。Listing 8-9给出了Listing 8-8的一个修改的版本,给出如何在XML布局中使用ViewStub。
Listing 8-9 ViewStub In XML
ViewStub stub = (ViewStub)findViewById(R.id.mystubid);
View inflatedView = stub.inflate(); // inflatedView将是定义在mylayout.xml中的布局
View view = findViewById(R.id.mystubid);
view.setVisibility(View.VISIBLE); // 使用inflated布局替换view stub
view = findViewById(R.id.myid); // 我们需要获取刚刚得到的inflated view
Listing 8-12 XML中的ViewStub,不覆盖ID
View view = findViewById(R.id.myid);
view.setVisibility(View.VISIBLE); // 使用inflated布局替换view stub
view = findViewById(R.id.myid); // 需要获取刚刚inflated view
View view = findViewById(R.id.myid);
view.setVisibility(View.VISIBLE); // 使用inflated layout替换view stub(如果在布局中使用stub)
if (view.getParent() == null) {
// 使用了stub,所以我们要使用新inflated view替换它
view = findViewById(R.id.myid);
} else {
// 不做任何事情,我们第一次找到的view是我们期望的
}
为了帮助你创建最好的布局,Android SDK提供了两个简单的工具:hierarchyviewer和layoutopt。你可以在SDK tools目录找到这些工具。
Android SDK有一个非常有用的工具查看和分析应用的布局:hierarchyviewer。作为事实,Figure 8-1和Figure 8-2都是使用这个工具产生的。除了给你应用布局的细节,这个工具同样测量它需要多长时间去测量、布局、draw每个widget,识别出哪个widget需要比较长的时间去测量、布局和draw。
你可以使用hierarchyviewer作为一个单独的工具,或者直接在Eclipse中使用Hierarchy View视图。
Android SDK有另外一个工具可以帮助你分析你的布局:layoutopt。这个工具分析你的布局文件,给出使布局更加有效的改变建议。
比如,对Listing 8-5布局使用layoutopt工具,得到如下的输出:
The root-level
事实证明,这是Listing 8-6做的。对Listing 8-6使用layoutopt不会有任何的提醒。
TIP:使用最新的layoutopt工具,以保证你得到最好的结果。
保证layoutopt工具报的所有的问题在发布应用前有认真的对待。不优化布局会使应用变慢,而补救这样的布局通常很简单。