经过一些实验,终于比较清楚地理解了 LayoutInflater 的真正作用.
这个实验要从一个问题说起: 为什么 Activity 里有 findViewById() 方法 , 而 View 里也有同样的 findViewById() ? 起初我以为这两个方法有什么地方是不一样的,但其实基本上是相同的, 同样的通过 id 获取自身的子组件 . 只是在Activity中它会间接返回Activity所使用的ViewContent的子组件.
看看我第一次实验的代码:(这是在 Mars Chen 老师的 Wifi 讲解那一课里顺便做的实验)
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); layout=new LinearLayout(this); LayoutInflater inflater= (LayoutInflater)layout.getContext().getSystemService(Service.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.main, layout, true); startWifiButt=(Button)layout.findViewById(R.id.startButton); stopWifiButt=(Button)layout.findViewById(R.id.stopButton); checkWifiButt=(Button)layout.findViewById(R.id.checkButton); startWifiButt.setOnClickListener(startClickListener); stopWifiButt.setOnClickListener(stopClickListener); checkWifiButt.setOnClickListener(checkClickListener); }
上面这段代码编译的结果失败了, 屏幕上生成三个Button, 但点击后没有反应.
值得留意的是 , 我的组件是通过 inflate 了 R.layout.main 产生一个main view的实例 layout ,通过这个layout 的 findViewById 方法去获取.
下面是成功了的代码:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); layout=new LinearLayout(this); LayoutInflater inflater= (LayoutInflater)layout.getContext().getSystemService(Service.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.main, layout, true); setContentView(layout); startWifiButt=(Button)layout.findViewById(R.id.startButton); stopWifiButt=(Button)layout.findViewById(R.id.stopButton); checkWifiButt=(Button)layout.findViewById(R.id.checkButton); startWifiButt.setOnClickListener(startClickListener); stopWifiButt.setOnClickListener(stopClickListener); checkWifiButt.setOnClickListener(checkClickListener); }
这一次,同样的 inflate 了一个 main view 的 layout 去获取组件. 但不同的是, 我把 activity 的 setContentView 中的ContentView set 成了 我自己 inflate 出来的那个 layout .
于是实验便证明了:
1. inflate 方法生成的是一个新的实例. inflate 多少次就会生成多少个 View 实例. 而不是返回某些已有的 View; 因此这 个新产生的 View 实例 与任何其他 View 实例都没有关联.
2. 在失败的例子中其实 findViewById() 并没有问题, 只是 activity 的 setContentView () 的 参数 R.layout.main 与 新生成的 layout 并没有关系 . 因此 显示的Button组件与 注册 OnClickListener 的组件并非同一批组件. 注册 Listener 的 Button 属于 layout 实例所有 , 而显示出来的是 R.layout.main