編輯:關於Android編程
Android:注解型框架原理淺析:在DataBinding框架出來之前,Android有很多很多注解型框架,但是隨著DataBinding的強勢崛起,大多注解型框架都走投無路了。但是為了更好的了解技術,還是寫了一個小小小的注解模型
作為一名初學者,已經厭煩了findViewById了,有沒有更簡單的辦法去獲取xml文件中的控件實例呢?使用注解就可以了。
注解:我們可以把它理解為是一種標記。通過反射機制+標記就能實現注解型框架了。
activity_main.xml
代碼著實太簡單了,就是定義了id分別為username和password的兩個TextView控件。
我的目標就是:自動獲取控件,並且為id為a的控件增加onClickListener監聽,id為b的控件增加onLongClickListener監聽。
我們先定義注解吧
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewAnnotation {
int viewId() default 0;
int layoutId() default 0;
int onClick() default 0;
int onLongClick() default 0;
}
這裡定義了四個方法,其實要使用的注解。因為寫了default,所以可以不同時使用者四個注解,viewId是用來獲取控件的,layoutId是為activity設置布局的,onClick是為了設置點擊事件監聽的,onLongClick是為了設置長按事件監聽的。
那我們開始在activity中使用這四個注解
@ViewAnnotation(layoutId = R.layout.activity_main)
public class MainActivity extends Activity {
@ViewAnnotation(viewId = R.id.username)
private TextView username;
@ViewAnnotation(viewId = R.id.password)
private TextView password;
@ViewAnnotation(onClick = R.id.username)
public void clickUsername(View view) {
Toast.makeText(this, "onClickListener", Toast.LENGTH_LONG).show();
}
@ViewAnnotation(onLongClick = R.id.password)
public void onLongClick(View view) {
Toast.makeText(this, "onLongClickListener", Toast.LENGTH_LONG).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewUtils.injectActivity(this);
username.setText("Aiden");
password.setText("123456");
}
}
可以看出,代碼變得非常簡單。在onCreate()函數中,寫了ViewUtils.injectActivity(this)。這是我自定義的ViewUtils類,然後不同findViewById了,因為我們用注解獲取了那個實例了。
public class ViewUtils {
// 注入activity
public static void injectActivity(Activity activity) {
Class activityClass = activity.getClass();
injectContentView(activity, activityClass);
injectView(activity, activityClass);
injectListener(activity, activityClass);
}
// 設置contentView的
private static void injectContentView(Activity activity, Class activityClass) {
if (activityClass.isAnnotationPresent(ViewAnnotation.class)) {
ViewAnnotation inject = activityClass.getAnnotation(ViewAnnotation.class);
int layoutId = inject.layoutId();
if (layoutId > 0) {
activity.setContentView(layoutId);
}
}
}
// 獲取控件的
private static void injectView(Activity activity, Class activityClass) {
Field[] fields = activityClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(ViewAnnotation.class)) {
field.setAccessible(true);
ViewAnnotation inject = field.getAnnotation(ViewAnnotation.class);
int id = inject.viewId();
if (id > 0) {
try {
field.set(activity, activity.findViewById(id));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
// 分別實現了點擊事件和長按事件的監聽
private static void injectListener(final Activity activity, Class activityClass) {
Method[] methods = activityClass.getDeclaredMethods();
for (final Method method : methods) {
if (method.isAnnotationPresent(ViewAnnotation.class)) {
ViewAnnotation ViewAnnotation = method.getAnnotation(ViewAnnotation.class);
int onClick = ViewAnnotation.onClick();
if (onClick > 0) {
activity.findViewById(onClick).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// 回調activity中的方法
method.invoke(activity, v);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
);
}
int onLongClick = ViewAnnotation.onLongClick();
if (onLongClick > 0) {
activity.findViewById(onLongClick).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
try {
// 回調activity中的方法
method.invoke(activity, v);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return false;
}
});
}
}
}
}
}
至此,一個簡單的注解型框架就形成了。當然了還有更多更多的細節需要處理的。比如說支持Fragment、反射控件的更多方法(如setAdapter() )等等。
作為小白,只知道這麼多了
自定義ViewGroup打造微信朋友圈之九宮圖效果
本文參考了manymore13文章邏輯,在此基礎上做了改進:1.可定義最大行數2.定義每行顯示幾張3.當圖片數量過多時設置更多圖片由於個人較懶,去掉了xml配置屬性,所有
Android自定義view系列之99.99%實現QQ側滑刪除效果實例代碼詳解
首先聲明本文是基於GitHub上baoyongzhang的SwipeMenuListView修改而來,該項目地址:https://github.com/baoyongzh
服務器基於PHP CodeIgniter,Android基於Volley實現多文件/圖片上傳(含服務器,web版和android客戶端完整代碼)
問題背景:app在上傳圖片時,同時傳遞參數,支持傳遞多個圖片。本文中的環境默認已經配好了服務器的CodeIgniter框架。事實上不使用這個框架也是可以的。 一,服務器部
Android中的 事件流----淺析安卓中的動與靜(三) 線程間通訊
任何程序都是靜態代碼,我們把這些靜態代碼打包好,然後放到運行環境當中,通過事件流的驅動使這些代碼運行起來。Android的環境也不例外。靜態的代碼,在動態事件的驅動下,才