自定的FindViewById注解,实现同名的R.id无需初始化

前一段时间在学习Java的注解,突发奇想,来一个安卓的FindViewById,能够自动适配同名的R.id,这用就不用每一个组件都要去做一次findViewById的初始化了

具体代码如下


FindViewById注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Kazz on 2016/9/9.
 * 以注解的形式初始化一些view
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FindViewById {
    /**
     * 给定默认值
     */
    public final int DEFAULT_VALUE = -31243249;

    int value() default DEFAULT_VALUE;
}



基础的Activity类(封装了一些常用方法以及实现注解的处理)

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;






import java.lang.reflect.Field;


/**
 * 基础的Activity,封装了一些公共方法
 */
public abstract class MyBaseActivity extends AppCompatActivity implements View.OnClickListener<span style="font-family: Arial, Helvetica, sans-serif;">{</span>


    protected final String TAG = getClass().getSimpleName();
    protected final String CURRENT_TAG = "MyBaseActivity";


    /**
     * 设置界面的R id的抽象方法,直接return R.layout.xxxx
     *
     * @return
     */
    protected abstract int getLayoutID();
    
    protected abstract void initUI();

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(getLayoutID());


        initViewAnnotation();
        initUI();


    }

    /**
     * 加载该Activity下有FindViewById注解的View
     */
    final private void initViewAnnotation() {
        Log.i(CURRENT_TAG, "initViewAnnotation: 开始");
        Field[] viewFields = getClass().getDeclaredFields();
        for (Field field : viewFields) {
            field.setAccessible(true);
            final String fieldName = field.getName();
            Log.d(CURRENT_TAG, "initViewAnnotation: 开始处理" + fieldName + "的注解");
            if (!PubTools.isViewClass(field.getType())) {
                Log.w(CURRENT_TAG, "initViewAnnotation: " + fieldName + "不是View的子类,不需要处理");
                continue;
            }
            if (field.isAnnotationPresent(FindViewById.class)) {
                FindViewById anno = field.getAnnotation(FindViewById.class);
                int rid = anno.value();
                Log.d(CURRENT_TAG, "initViewAnnotation: 这个view有注解,view是{},注解值为{},类型是{}", fieldName, rid, field.getType());


                if (rid == FindViewById.DEFAULT_VALUE) {  //如果注解的是空(即默认值,则直接反射R.id里面的同名属性)
                    try {
                        Field ridField = R.id.class.getField(fieldName);
                        rid = ridField.getInt(new R.id());
                        Log.d(CURRENT_TAG, "initViewAnnotation: 这个属性注解的是默认值,获得的R.id是" + rid);
                        field.set(MyBaseActivity.this, findViewById(rid)); //给其设值
                    } catch (NoSuchFieldException e) {
                        Log.e(CURRENT_TAG, "initViewAnnotation: 没有找到" + fieldName + "对应的R.id,无法完成初始化,程序将退出!");
                        throw new RuntimeException();
                    } catch (Exception e) {
                        Log.e(CURRENT_TAG, "initViewAnnotation: 给" + field.getName() + "设置失败");
                        throw new RuntimeException();
                    }
                } else {
                    try {
                        field.set(MyBaseActivity.this, findViewById(rid)); //给其设值
                    } catch (IllegalAccessException e) {
                        Log.e(CURRENT_TAG, "initViewAnnotation: 给" + field.getName() + "设置失败");
                    }
                }
            }
           try {
                View view = (View) field.get(MyBaseActivity.this);
                view.setOnClickListener(this);
            } catch (IllegalAccessException e) {
                Log.e(CURRENT_TAG, "initViewAnnotation: 给组件{}添加Onclicklistener出错,{}", fieldName, Arrays.toString(e.getStackTrace()));
           }
        }
        Log.i(CURRENT_TAG, "initViewAnnotation: 结束");
    }


    final protected void showToast(String message) {
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
    }


}




实际使用

package com.kazz.SaveMoney2;

import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends MyBaseActivity {

    @FindViewById(R.id.tv_h)
    private TextView tv_h;


    @FindViewById()
    private Button bt_anno;



    @Override
    protected int getLayoutID() {
        return R.layout.activity_main;
    }



    @Override
    public void initUI() {

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_anno:{
                showToast("点击注解按钮");
                break;
            }
            case R.id.tv_h:{
                showToast("点击就送屠龙宝刀");
                break;
            }
            default:{
                Log.i(TAG,"点击了{}组件",v.getId());
            }
        }
    }
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值