开发android应用时,在activity中总是要写很多findViewById来获取XML布局中的各种组件,而它们都是相似的,只是组件类型和id不同而已,根据DRY原则,我们可以把一些
相同的代码进行封装,这样就节省了很多代码量,在一个复杂的activity中不会显得臃肿。
我们可以写一个类,利用反射来实现,通过反射获得各个组件并初始化它们:
AndFrameWork.java如下所示:
package com.example.andframework;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.view.View;
public class AndFrameWork {
/**
* 初始化组件
* @param context
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws NoSuchFieldException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public static void initComponent(Activity context) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException, InvocationTargetException{
//获得Class对象实例
Class clazz = context.getClass();
//获得context所有属性
Field[] fields = clazz.getDeclaredFields();
//遍历fields
for (Field field : fields) {
//获得属性名
String fieldName = field.getName();
//获得set方法名
String setMethodName = "set" + initCap(fieldName);
//获得set方法
Method setMethod = clazz.getDeclaredMethod(setMethodName, field.getType());
String packageName = "com.example.andframework";
//R类的Class实例
Class Rclazz = Class.forName(packageName + ".R$id");
//获得组件的id值
Field fName = Rclazz.getDeclaredField(fieldName);
int id = fName.getInt(null);
//通过findViewById获得UI视图
View view = context.findViewById(id);
//将视图设置到界面属性中
setMethod.invoke(context, view);
}
}
/**
* 对给定字符串进行首字母大写
* @param name
* @return
*/
public static String initCap(String name){
StringBuilder sb = new StringBuilder(name.substring(0,1).toUpperCase());
sb.append(name.substring(1));
return sb.toString();
}
}
MainActivity.java如下所示:
package com.example.andframework;
import java.lang.reflect.InvocationTargetException;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
//声明个组件属性,注意名字要跟XML中id值相同,提供set get方法
private TextView textView1;
private Button button1;
private Button button2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// textview1 = (TextView) findViewById(R.id.textView1);
// button1 = (Button) findViewById(R.id.button1);
// button2 = (Button) findViewById(R.id.button2);
//调用initComponent方法初始化视图界面
try {
AndFrameWork.initComponent(this);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//设置监听器
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "反射测试完毕!", Toast.LENGTH_SHORT).show();
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
textView1.setText("世界,你好!");
Toast.makeText(getApplicationContext(), "上面文字以改变!", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public TextView getTextView1() {
return textView1;
}
public void setTextView1(TextView textView1) {
this.textView1 = textView1;
}
public Button getButton1() {
return button1;
}
public void setButton1(Button button1) {
this.button1 = button1;
}
public Button getButton2() {
return button2;
}
public void setButton2(Button button2) {
this.button2 = button2;
}
}