通过对inflate与 findViewById 方法的探究深度了解一下Android
===================================================================
在实际开发中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); } }); }}
SubActivity.java 这个Activity是测试的关键
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
更多相关文章
- android 中 application 的使用
- [置顶] Android(安卓)65K问题之Multidex原理分析及NoClassDefFou
- Android(安卓)Unit Test学习
- android关于多dex打包的理解
- Android(安卓)强大的开发支持库组件AppFromwork框架详解
- Android开发实例详解之IMF(Android(安卓)SDK Sample—SoftKeyboar
- 浅谈Java中Collections.sort对List排序的两种方法
- 类和 Json对象
- Python list sort方法的具体使用