用膩了千篇一律的findViewById 拷貝 粘貼,是時(shí)候搞點(diǎn)創(chuàng)新,提升一點(diǎn)逼格了。
問題點(diǎn):
1.每個(gè)view屬性去findViewById,如果控件過多,感覺代碼里一大片的findViewById,拷貝粘貼的手疼,想著怎么去自動(dòng)遍歷獲取;
2.view與xml里的id綁定,想想怎么簡(jiǎn)單一行代碼就可以實(shí)現(xiàn)綁定。
最后,用反射和注解分別可以完美解決以上兩點(diǎn)需求。
首先定義一個(gè)自定義注解:
<pre>
/**
* Created by Andy on 2017/3/9 0009.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewField {
//? ? public int value();? //如果默認(rèn)定義是value,則在使用是默認(rèn)是? @ViewField(R.id.back)
public int id();// 使用:@ViewField(id=R.id.back)
}
</pre>
以及使用:
@ViewField(id=R.id.back)
ImageView back;
@ViewField(id=R.id.album_cover)
ImageView albumCover;
@ViewField(id=R.id.song_info)
private TextView songInfo;
@ViewField(id=R.id.current_time)
TextView position;
@ViewField(id=R.id.total_time)
TextView duration;
@ViewField(id=R.id.seek_bar)
SeekBar seekBar;
@ViewField(id=R.id.play_mode)
ImageView playMode;
@ViewField(id=R.id.prev)
ImageView pre;
@ViewField(id=R.id.next)
ImageView next;
@ViewField(id=R.id.play)
ImageView play;
@ViewField(id=R.id.list)
ImageView list;
使用反射,獲取activity里的每個(gè)view 控件field,然后獲取id的控件對(duì)象,對(duì)field賦值
public static void inject(Activity activity){
//獲取activity對(duì)象的實(shí)際類別
Class atyCls = activity.getClass();
//獲取類自定義的成員,不包括繼承自父類的成員
Field[] fields = atyCls.getDeclaredFields();
for(Field field:fields){
//成員屬性是否有ViewField注解
ViewField vf = field.getAnnotation(ViewField.class);
if(vf != null){
//通過反射,獲取atyCls的findViewById方法
try {
int id = vf.id();
//指定方法名 和 參數(shù)類別列表(方法重載,需要指定參數(shù)詳細(xì))
//findViewById是從父類繼承來的,所以用getMethod,而不是getDeclaredMethod
Method method = atyCls.getMethod("findViewById",int.class);
//調(diào)用方法,指定參數(shù)
Object view = method.invoke(activity,id);
//可訪問
field.setAccessible(true);
//給成員屬性賦值
field.set(activity,view);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
最后是調(diào)用和驗(yàn)證:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hjmusic_playing);
ViewAnnotationUtils.inject(this);
back.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
finish();
}
});
}
發(fā)現(xiàn)點(diǎn)擊回退圖標(biāo)按鈕,界面退出,表示賦值成功。
注意 getMethod和getDeclaredMethod的區(qū)別,前者包含了從父類繼承的method,后者僅包含自己定義的method.