最近来到一家新公司, 公司的项目用到了很多第三方框架, 比如Retrofit, ButterKnife, EventBus等等, 里面很多地方都用到了注解.现在项目上线了, 闲来无事, 也随手写一下类似于ButterKnife的功能, 就以findViewById和Onclick事件为内容, 利用注解实现其功能. 下面闲话少说, 上代码~~~~~~
首先创建一个关于findViewById的注解类. 基本形式@interface.
为了实现注解能够存活且在jvm中运行需要加上元注解@Retention(RetentionPolicy.RUNTIME).
package com.example.chanp.testannotation.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by sjx on 2018/4/16.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface FindId {
int value() default 0;
}
创建一个OnClick的注解类
package com.example.chanp.testannotation.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by sjx on 2018/4/16.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface FindClick {
int id() default 0;
}
测试用的Activity
package com.example.chanp.testannotation;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.example.chanp.testannotation.annotation.AnnotationHelper;
import com.example.chanp.testannotation.annotation.FindClick;
import com.example.chanp.testannotation.annotation.FindId;
/**
* Created by sjx on 2018/4/16.
*/
public class TestActivity extends AppCompatActivity implements View.OnClickListener{
@FindId(R.id.text_1)
TextView text_1;
@FindId(R.id.text_2)
TextView text_2;
TextView text_3;
@FindClick(id=R.id.text_onclick)
TextView text_onclick;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_test_annotation);
AnnotationHelper.getInstance().init(this);
if (text_1 != null){
text_1.setText(this.getClass().getSimpleName()+" onCreate text_1");
}
if (text_2 != null){
text_2.setText(this.getClass().getSimpleName()+" onCreate text_2");
}
}
public void onClick(View view){
switch (view.getId()){
case R.id.text_onclick:
Toast.makeText(this, "text_onclick Onclick...", Toast.LENGTH_SHORT).show();
break;
}
}
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="22dip"
android:textSize="20sp"/>
<TextView
android:id="@+id/text_2"
android:layout_marginTop="20dip"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_3"
android:layout_marginTop="20dip"
android:text="text_3"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_onclick"
android:layout_marginTop="20dip"
android:text="Onclick"
android:padding="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
下面就是注解的读取, 注解提取和处理, 是给编译器和APT(Annotation Processing Tool)用的.
下面就是利用反射读取值,并且赋值的过程.
package com.example.chanp.testannotation.annotation;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
import java.lang.reflect.Field;
/**
* Created by sjx on 2018/4/16.
*/
public class AnnotationHelper {
private static final String TAG = "AnnotationHelper";
private static class InstanceHelper{
public static final AnnotationHelper instance = new AnnotationHelper();
}
public static AnnotationHelper getInstance(){
return InstanceHelper.instance;
}
public void init(Activity ctx){
Class clzz = ctx.getClass();
Field[] fields = clzz.getDeclaredFields();
for (Field field : fields){
field.setAccessible(true);
if (field.isAnnotationPresent(FindId.class)){ //参数
FindId findId = field.getAnnotation(FindId.class);
Log.i(TAG, "field name : " + field.getName() + " value : " + findId.value());
try {
field.set(ctx, ctx.findViewById(findId.value()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (field.isAnnotationPresent(FindClick.class)){
FindClick findClick = field.getAnnotation(FindClick.class);
try {
Log.i(TAG, "field name : " + field.getName() + " value : " + findClick.id());
View view = ctx.findViewById(findClick.id());
view.setOnClickListener((View.OnClickListener) ctx);
field.set(ctx, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
然后赋值和点击事件就出来了~
效果图:
随手一写, Mark一下.