这个题目,可能或多有一些的夸张,实际上是这样的。也不能说是摆脱吧,最终还是要使用findviewbyid的!!
事情是这样的,大家在普通开发的时候,是不是经常的遇到这样的一个问题.Android开发的过程中,其实极大的使用了Mvc的这种设计模式,我也是最近深有感触。
一般的应用:如果按照我的思维,我会将其大体的分为三类,model,view.xml,与view.java,model不用说,肯定是模型类,view.xml就是布局文件,而view.java则是
用于将数据绑定给xml的一个控制类吧,哈哈,说得可能不标准。大家在开发的过程中,是不是深有感触,就是在执行第三步的时候,使用view.java,将传入的数据绑定到view.xml
界面元素中,大量的使用findviewbyid,来对各个组件进行实例化,这点是不是特烦人?对,很烦人的,如果说界面的元素稍微的少一些,还行,写得还挺代感 的,如果说界面的元素多了的话,那是有点痛苦了。
后面我就想,能不能让应用自动的 为我们生成这一些代码,也就是实例化控件的代码?
1)首先想到的就是反射,再通过递归的方式,将界面的所有元素全部例举出来,根据相应控件进行代码的拼接。当然,其实,在在遍历的过程中,完全可以实例化,创建相应的组件,考虑到运行时如果是这种方法的话,程序的运行效率会很低。后面和一位朋友讨论了一下,采用了代码拼接的方式。接下来就一起来看看怎么一步一步实现的。
如以下的是view.xml的布局文件
代码如下 :(博客园上面的代码上传实在是不好使)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/container">
<EditText
android:id="@+id/user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="DoGet">
<requestFocus />
</EditText>
<EditText
android:id="@+id/pass_word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="DoGet123"/>
<Button
android:id="@+id/login_nopass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ButtonLogin" />
<Button
android:id="@+id/login_web"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="web" />
<Button
android:id="@+id/login_wap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="wap" />
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
activity前台使用类:
package com.doget.froeachview;//http://ssyinxx.blog.163.com/blog/static/187302318201282033017883/
import java.lang.reflect.Field;
import java.util.HashMap;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.doget.updateapk.UpdateManager;
import com.doget.xmpp_demo.R;
public class Foreach_Act extends Activity {
LinearLayout linear;
String temp = "";
UpdateManager manager;
HashMap<String, String> maps = new HashMap<String, String>();
public Foreach_Act() {
// TODO Auto-generated constructor stub
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.wifi_demo);
// 找到最外层的容器
ViewGroup v = (ViewGroup) findViewById(R.id.container);
// 找到R.id类,得到其所有的属性以极相应的值
Field[] fields = R.id.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
// Log.i("field",
// "fieldinfo field_name"+fields[i].getName()+" field_value:"+fields[i].get(R.id.class).toString());
maps.put(fields[i].get(R.id.class).toString(),
fields[i].getName());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
findChildView(v);
Log.i("finalCode", temp);
Toast.makeText(this, "执行", 1000).show();
// 自动更新测试
Log.i("finalCode", "开始更新22222");
manager = new UpdateManager(this);
manager.checkUpdate();
Log.i("finalCode", "开始更新33333");
}
public void findChildView(ViewGroup v) {
for (int i = 0; i < v.getChildCount(); i++) {
View obj = v.getChildAt(i);
// 这下边暂时就先例举出来以如下这一些,当然还有其它的一些类型
if (obj instanceof Button) {
// 判断是否在R文件中有定义,如果有定义,则为其创建代码
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
} else if (obj instanceof TextView) {
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
}
if (obj instanceof LinearLayout) {
LinearLayout linear = (LinearLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +" classname-->"+obj.getClass().getSimpleName());
findChildView(linear);
}
if (obj instanceof RelativeLayout) {
RelativeLayout rela = (RelativeLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +" classname-->"+obj.getClass().getSimpleName());
findChildView(rela);
}
}
}
// (类型) 名称=(类型)findViewById(数值);
// (类型) ddd=(类型)findViewById(数字);
public String createCode(String type, String name) {
// 这个地方,可以根据大家要求进行更改
String code = type + " " + name + " =(" + type
+ ")findViewById(R.id." + name + ");";
return code + "
";
}
}
快来看看,竟然生成了:
形式,有多种,大家可以根据自己的需要进行更改。同时,需要注意的一下是,要使用这个方法,得有一个初始的寻找起点,就是视图最外层的那个容器必须得有一个id,不然,就不会再往下找了。通过这种方式,把生成的代码,往自己的代码里面一放,是不是快多了。但是,这好像第三方调用起来是乎还有一些的麻烦。还是封装一下吧。
package com.doget.froeachview;
import java.lang.reflect.Field;
import java.util.HashMap;
import com.doget.xmpp_demo.R;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class sffindview {
View mView=null;
String temp = "";
String viewname="";
HashMap<String, String> maps = new HashMap<String, String>();
/**
* 参数:上下文,R.id类文件,需要查找 的视图,查找 的起点id,视图名称
*/
public sffindview(Context context,Class r_id,int resourceid,int originid,String viewname) {
// TODO Auto-generated constructor stub
mView=LayoutInflater.from(context).inflate(resourceid, null);
// 找到最外层的容器
ViewGroup v = (ViewGroup) mView.findViewById(R.id.container);
// 找到R.id类,得到其所有的属性以极相应的值
Field[] fields = r_id.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
// Log.i("field",
// "fieldinfo field_name"+fields[i].getName()+" field_value:"+fields[i].get(R.id.class).toString());
maps.put(fields[i].get(R.id.class).toString(),
fields[i].getName());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.viewname=viewname;
Log.i("net", "代码开始生成.......................................................................");
findChildView(v);
Log.i("net", temp);
Log.i("net", "代码生成完毕.......................................................................");
}
public void findChildView(ViewGroup v) {
for (int i = 0; i < v.getChildCount(); i++) {
View obj = v.getChildAt(i);
// 这下边暂时就先例举出来以如下这一些,当然还有其它的一些类型
if (obj instanceof Button) {
// 判断是否在R文件中有定义,如果有定义,则为其创建代码
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
} else if (obj instanceof TextView) {
if (maps.get(String.valueOf(obj.getId())) != null) {
temp += createCode(obj.getClass().getSimpleName(),
maps.get(String.valueOf(obj.getId())));
}
}
if (obj instanceof LinearLayout) {
LinearLayout linear = (LinearLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +" classname-->"+obj.getClass().getSimpleName());
findChildView(linear);
}
if (obj instanceof RelativeLayout) {
RelativeLayout rela = (RelativeLayout) obj;
// Log.i("findview", "linear-----id:"+obj.getId()
// +" classname-->"+obj.getClass().getSimpleName());
findChildView(rela);
}
}
}
// (类型) 名称=(类型)findViewById(数值);
// (类型) ddd=(类型)findViewById(数字);
public String createCode(String type, String name) {
// 这个地方,可以根据大家要求进行更改
String code="";
if(viewname==null||viewname.equals(""))
{
code = type + " " + name + " =(" + type
+ ")"+viewname+"findViewById(R.id." + name + ");";
}
else
{
code = type + " " + name + " =(" + type
+ ")"+viewname+".findViewById(R.id." + name + ");";
}
return code + "
";
}
}
使用代码: sffindview sf=new sffindview(this, R.id.class, R.layout.wifi_demo, R.id.container, "sf");
执行结果:
欢迎大家扩展!!!!好了,今天讲到 这里!!!