Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android框架進階--ThinkAndroid注解機制

Android框架進階--ThinkAndroid注解機制

編輯:關於Android編程

由於項目需要,開始研究ThinkAndroid。   個人認為該框架的注解機制十分新穎,所以先研究這個,順便學習下 Java 的annotation。   粗略的看了看,該機制在BaseActivity中初始化。而BaseActivity是所有Activity的基類。   對BaseActivity進行了代碼剖離,發現在BaseActivity中在onCreate函數裡啟動注解機制。   首先注入布局資源(綁定layout布局) 其次注入成員資源(綁定組件資源) 然後注入成員變量(初始化普通變量) 暫時先搞清楚第二個,怎麼綁定組件資源的:   我寫了個小demo,MyAnno     InjectView.java   [java]   package com.myanno;      import java.lang.annotation.ElementType;   import java.lang.annotation.Retention;   import java.lang.annotation.RetentionPolicy;   import java.lang.annotation.Target;         /**   * 自定義注解,獲取資源ID   * @使用方法   *              @InjectView(id = R.id.settingIv)   *              private ImageView imgSetting;    *    * @author      [email protected]   * @date        2013-10-29   * @description @Retention: 定義注解的保留策略   *              @Retention(RetentionPolicy.SOURCE)  //注解僅存在於源碼中,在class字節碼文件中不包含   *              @Retention(RetentionPolicy.CLASS)   //默認的保留策略,注解會在class字節碼文件中存在,但運行時無法獲得,   *              @Retention(RetentionPolicy.RUNTIME) //注解會在class字節碼文件中存在,在運行時可以通過反射獲取到   *              @Inherited                          //說明子類可以繼承父類中的該注解   *   *              @Target(ElementType.TYPE)           //接口、類、枚舉、注解   *              @Target(ElementType.FIELD)          //字段、枚舉的常量   *              @Target(ElementType.METHOD)         //方法   *              @Target(ElementType.PARAMETER)      //方法參數   *              @Target(ElementType.CONSTRUCTOR)    //構造函數   *              @Target(ElementType.LOCAL_VARIABLE) //局部變量   *              @Target(ElementType.ANNOTATION_TYPE)//注解   *              @Target(ElementType.PACKAGE)        //包      */      @Target(ElementType.FIELD)   @Retention(RetentionPolicy.RUNTIME)   public @interface InjectView   {       /** View的ID */       public int id() default -1;   }     MainActivity.java [java]   package com.myanno;      import java.lang.reflect.Field;      import android.app.Activity;   import android.os.Bundle;   import android.util.Log;   import android.view.View;   import android.widget.ImageView;   import android.widget.TextView;      public class MainActivity extends Activity {          /** 注解綁定UI元素 */       @InjectView(id=R.id.myimgview)       ImageView myimageview;              @InjectView(id=R.id.mytext)       TextView mytext;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_main);                      //初始化注解綁定的成員變量           injectView(this);                      //直接使用UI元素           mytext.setText("Text0");           myimageview.setImageResource(R.drawable.junny);       }              /** 實例化@InjectView 注解的成員*/       public void injectView(Activity activity)       {           Field[] fields = activity.getClass().getDeclaredFields();   //得到Activity中的所有定義的字段           if (fields != null && fields.length > 0)           {               for (Field field : fields)               {                   if (field.isAnnotationPresent(InjectView.class))                    //方法返回true,如果指定類型的注解存在於此元素上                   {                       Log.i("Field", field.toString());                                              InjectView mInjectView = field.getAnnotation(InjectView.class); //獲得該成員的annotation                       int viewId = mInjectView.id();                                  //獲得該注解的id                       View view=activity.findViewById(viewId);                        //獲得ID為viewID的組件對象                                              Log.i("Field", String.valueOf(viewId));                       Log.i("Field", view.getClass().toString());                                              try                       {                           field.setAccessible(true);  //設置類的私有成員變量可以被訪問                           field.set(activity, view);  //field.set(object,value)===object.fieldValue = value                       } catch (Exception e) { e.printStackTrace();}                   }                   else                       Log.i("Field", "該字段沒有被注解");               }           }       }   }     布局文件 activity_main.xml [html]  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"       xmlns:tools="http://schemas.android.com/tools"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:background="#000000"       android:orientation="vertical"       tools:ignore="ContentDescription" >       <ImageView           android:id="@+id/myimgview"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_gravity="center"/>       <TextView           android:id="@+id/mytext"           android:layout_width="match_parent"           android:layout_height="0dp"           android:layout_weight="1"           android:gravity="center"           android:background="@android:color/darker_gray"           android:textSize="30sp" />   </LinearLayout>     實驗結果   即注入成功了      需要說下我遇到的問題,在以上的基礎上,如果將布局文件裡的TextView 和ImageView兩個布局換個位置,這時候再運行下,會出現空指針異常。   將Log向上翻會發現一個警告     即非法參數異常   定位到這一行   [java]   field.set(activity, view);     通過觀察Log打印的日志   發現第一二行是對的,即獲得注解的類型和ID(ImageView 2131230720)都是正確的,但是通過findViewById獲取view的時候,Log第三行顯示的卻是TextView。   百思不得其解,最後無賴之下,清理一下項目,搞定。   我不知道是怎麼回事,暫且推測為資源緩存吧。  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved