1. 程式人生 > >java 中的 自定義viewUtils框架

java 中的 自定義viewUtils框架

exce stack wid policy his tools line idg 字節碼

在前面學習的基礎上,我們自己編寫一個ViewUtils註解框架類,不清楚的原理看前面的源代碼

package im.weiyuan.com.viewutils;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends
AppCompatActivity { @ViewInject(R.id.tv_main_title) private TextView tv_main_title; private Button btn_main; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //這裏一定要初始化註解
ViewUtils.inject(this); } //login的參數必須是 View view @OnClick(R.id.btn_main) public void login(View view ){ Toast.makeText(MainActivity.this,"事件被點擊了",Toast.LENGTH_LONG).show(); } }

package im.weiyuan.com.viewutils;

import java.lang.annotation.ElementType;
import
java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by wei.yuan on 2017/7/21. */ //指定註解的聲明周期 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface OnClick { int value(); }
package im.weiyuan.com.viewutils;

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

/**
 * Created by wei.yuan on 2017/7/21.
 */
//指定註解的聲明周期
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface  ViewInject{
    int value(); //如果這裏定義成id int id();用戶在使用的時候必須寫成     @ViewInject(id = R.id.tv_main_title),如果定義成int value();
    // [email protected](R.id.tv_main_title)
}
package im.weiyuan.com.viewutils;

import android.app.Activity;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by wei.yuan on 2017/7/21.
 */

public class ViewUtils {
    public  static  void inject(Activity activity){
               bindView(activity);
               bindBtn(activity);
    }


    /**
    * 對按鈕進行操作
    * **/

    private static void bindBtn(final Activity activity) {
      Class clazz = activity.getClass();

        /**
         * 獲得所有的方法
         * */
        Method[] methods = clazz.getDeclaredMethods();

        /***
         * 多所有的方法進行遍歷
         * */
        for(final Method method:methods){
            /**
             * 看該方法上是否存在註解標簽
             * */
            final OnClick annotation = method.getAnnotation(OnClick.class);
            if(annotation != null){
                /**
                 * 獲得註解標簽中的值 @OnClick(R.id.btn_main) ,這裏的值就是 R.id.btn_main
                 * */
                int resId = annotation.value();

                /**
                 * 獲得該對象
                 * */
                final View btnView = activity.findViewById(resId);

                /**
                 * 給view 綁定點擊監聽事件
                 * */

               btnView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View v) {
                       /**
                        * 在點擊事件之後執行反射的回調方法
                        * 匿名內部類訪問當前函數的局部變量,局部變量聲明為final類型
                        * */
                       method.setAccessible(true);
                       try {
                           method.invoke(activity,btnView);
                       } catch (IllegalAccessException e) {
                           e.printStackTrace();
                       } catch (InvocationTargetException e) {
                           e.printStackTrace();
                       }
                   }
               });

            }
        }
    }


    private   static  void bindView(Activity activity){
        //首先獲得activity的所有字段,利用反射
        Class clazz = activity.getClass();
        //獲得該字節碼中的所有字段信息
        Field[] fields = clazz.getDeclaredFields();
        //對字段進行遍歷,看給那些字段添加了註解的標簽
        for(Field field :fields){
            ViewInject annotation = field.getAnnotation(ViewInject.class);
            if(annotation != null){
                /**
                 * 獲得當中註解上的值
                 * */
                int resId = annotation.value();

                /**
                 * 通過activity 的findViewById獲得當前的控件
                 * */
                View view = activity.findViewById(resId);

                /**
                 * 通過反射將view的值設置給當前的字段
                 * */
                field.setAccessible(true);

                /**
                 * 給activity的field字段賦值為view對象
                 * */

                try {
                    field.set(activity,view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="im.weiyuan.com.viewutils.MainActivity">

    <TextView
        android:id="@+id/tv_main_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:text="點擊"
        android:id="@+id/btn_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

相當的經典

java 中的 自定義viewUtils框架