===================================================================
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。
具体作用:
1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;
2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。
LayoutInflater作用是将layout的xml布局文件实例化为View类对象。
注意:
·inflate方法与 findViewById 方法不同;
·inflater 是用来找 res/layout下的 xml 布局文件,并且实例化;
·findViewById() 是找具体 xml 布局文件中的具体 widget控件(如:Button、TextView 等)。
====================================================================
上述就是目前小编找到的最靠谱的说法了,但是讲的依然有一些小瑕疵,不够深入。
首先,小编认为.inflate方法与findViewById方法不是类似的,而是完全两个领域的方法,根本没有可比性。
其次,也是非常重要的一点是上述的最后一句话理解有误,暴露了对底层原理理解的偏差。
小编是这样理解的:我们可以把*.xml布局文件理解为“模板”,就像在学习Java时我们知道的,类是对象的“模板”一样。所以,就像Java的虚拟机会根据我们写的类实例化成一个个的对象一样,Android也会根据我们写的.xml文件实例化出View对象。而Android应用就是靠这一个个的View对象构建起庞大而复杂的APP的。所以,在Android的UI开发中,应时刻记得我们是在操作着一个个的View对象,而不是.xml文件,把对那些方法的理解联系到对象上。
inflate方法的作用就是根据.xml文件,实例化出一个对象来。如:
根据这个“模板”,系统会为我们实例化出一个包含了两个Button形子View对象的LinearLayout形的ViewGroup父对象,所以不知不觉之间,其实我们创建了起码3个对象。而这就是inflate方法的实际意义——生成对象。
再来看看findViewById,这个方法其实是基于父View对象进行的。比如说上面被实例化出来的LinearLayout对象,我们如果想找到它所包含的某个Button对象,就有可能用到findViewById方法。以识别Id的方式来查找子对象。所以findViewById的实际意义是——查找对象(不生成对象,而是找到它并返回它)。
下面小编就通过测试代码带大家理解一下Android这个平台的局部原理。
main_activity.xml:
activity_sub.xml:
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.testcontentprovider2.MainActivity">
下面给出两个Activity代码,会在代码中伴随讲解原理
MainActivity.java
public class MainActivity extends Activity {
Buttonbtn1;
Buttonbtn2;
Buttonbtn3;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button)findViewById(R.id.btn1);
btn2 = (Button)findViewById(R.id.btn2);
btn3 = (Button)findViewById(R.id.btn3);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
System.out.println("MainActivity's btn1 pressed!");
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
System.out.println("MainActivity's btn2 pressed!");
}
});
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
Intentintent = new Intent(MainActivity.this, SubActivity.class);
startActivity(intent);
}
});
}
}
public class SubActivity extends Activity {
Buttonbtn;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
// TODOAuto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
btn =(Button) findViewById(R.id.sub_add);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
addTestView();
}
});
}
private voidaddTestView() {
//找到当前Activity下的一个View容器,准备用这个容器去addView
finalLinearLayout ll = (LinearLayout)findViewById(R.id.test_linear);
//这里的动作就是寻找,因为整个布局的对象已经在setContentView(R.layout.activity_sub);代码执行完成后就已经实例化出来了,我们要找的LinearLayout就在这个大对象里,是它的一个子对象。
//渲染出即将被添加的View(下面就是另一个实例化操作)
LayoutInflater li = LayoutInflater.from(this);
finalLinearLayout view = (LinearLayout) li.inflate(
R.layout.activity_main, null);
//可见,即将被添加的View就是用的MainActivity的xml模板实例化出来的,这样就是为了测试该View下的按钮btn1btn2是否会与MainActivity中的按钮混淆(当然,我们可以预测到,如果混淆,那就说明我们的组件是"模板化"的,否则,我们的组件则是"对象化"的)
ll.addView(view);
//分别用两种不同的方法给即将被添加的View中的btn1和btn2添加点击事件
// 方法1
Button btn1= (Button) view.findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
System.out.println("SubActivity's btn1 pressed!");
}
});
// 方法2
Button btn2= null;
for (int i =0; i < view.getChildCount(); i++) {
int id =view.getChildAt(i).getId();
if (id ==R.id.btn2) {
btn2 =(Button) view.getChildAt(i);
}
}
if (!(btn2== null)) {
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public voidonClick(View v) {
// TODOAuto-generated method stub
System.out.println("SubActivity's btn2 pressed!");
}
});
}
}
}
之所以可以用方法2,是因为这里的父View即变量view是LinearLayout,而不仅仅是View,LinearLayout是继承自ViewGroup的,所以它可以getChild,如果是直接继承自View的子类是没有Child可言的
以上均测试完毕后不难总结出来:R.id.btn1这个int值(存在于R.java文件中)不是某个按钮的唯一标识,而是btn1按钮的"模板"的唯一标识,而我们可以通过xml模板在不同的地方产生不同的btn1对象,这些对象都是相互独立存在的,而我们用到R.id.btn1这个int值仅仅是在某地"寻找"btn1对象的时候用到的一个匹配工具
还是那句话,每在某个角度了解了一些后,都会突然对Android感到陌生,感觉又重新认识了她一样。
附上源码:http://pan.baidu.com/s/1i31NK0l