Android AOP之路三 Android上的註解


一、簡介


啥是註解,不懂的可以先看我上一篇文章。


在android 裡面 註解主要用來幹這麼幾件事:



  • 和編譯器一起給你一些提示警告信息。

  • 配合一些ide 可以更加方便快捷 安全有效的編寫java代碼。谷歌出的support-annotations這個庫 就是主要幹這個的。

  • 和反射一起 提供一些類似於spring 可配置的功能,方便簡潔。


二、Support Annotations栗子


這裡使用官方的一個庫,說明在開發中的簡單一個應用。


2.1 導包


在新建項目的時候會自動導的,可以看build.gradle中的依賴dependencies是這樣的。


dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.1'
testCompile 'junit:junit:4.12'
}

如果沒有的話,自己在build.gradle的依賴添加(xx.x.x為你的compileSdkVersion版本號):


compile 'com.android.support:support-annotations:xx.x.x'

2.2 使用


這時候就可以使用一些support-annotations提供的註解,下面舉一些栗子:


1、 @NonNull


test方法參數添加瞭一個NonNull註解,然後我們傳遞一個空的參數過去。


public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

String s = null;
test(s);
}

public void test(@NonNull String s){
System.out.println(s);
}

}

IDE就會提示警告



2、 @StringRes


再定義testString方法參數添加瞭一個StringRes註解,然後我們傳遞一個數字過去。


public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

testString(112312);
testString(R.string.app_name);
}

public void testString(@StringRes int s){
System.out.println(s);
}

}

IDE就會提示



三、實現自己的ButterKnife


經過之前的知識,我們已經知道註解的原理和使用瞭,這裡實現ButterKnife的一個簡單功能,View的註入: 一個註解,一個解析器即可。


3.1 BindView註解



@Target(ElementType.FIELD) //解析常量
@Retention(RetentionPolicy.RUNTIME) //運行時
public @interface BindView {
int value() default -1; //標識控件
}

3.2 BindViewParser解析器


/**
* Created by Litp on 2017/2/17.
*/
public class BindViewParser {

/**
* 傳遞activty或者View 對象,使用反射獲取view變量
* @param object
*/
public static void inject(Object object) {

try {
parse(object);
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 解析獲取值
* @param object
* @throws Exception
*/
public static void parse(Object object) throws Exception {

final Class<?> clazz = object.getClass();

View view = null;

//獲取clazz的變量,不論private還是public
Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {

//這個變量 是否有BindView註解
if (field.isAnnotationPresent(BindView.class)) {
//獲取這個變量對應的註解
BindView injectView = field.getAnnotation(BindView.class);
//獲取值
int id = injectView.value();
if (id <= 0) {
throw new Exception("View的id不能為空");
} else {
//設置可以訪問
field.setAccessible(true);
//獲取view
if (object instanceof View) {
view = ((View) object).findViewById(id);
} else if (object instanceof Activity) {
view = ((Activity) object).findViewById(id);
}
//設置View
field.set(object, view);
}

}

}

}

}

3.3 Activity使用


public class MainActivity extends AppCompatActivity {

//使用註解標識變量
@BindView(R.id.tv_test)
TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//傳遞當前activty給解析器,進行初始化view
BindViewParser.inject(this);

//這裡就已經是初始化完畢瞭,可以進行使用瞭
textView.setText("測試自己的註入demo");

}

}

0 個評論

要回覆文章請先登錄註冊