開發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;
}
}