Android開發學習之路-讓註解幫你簡化代碼,徹底拋棄findViewById

來源:互聯網
上載者:User

標籤:

本文主要是記錄註解的使用的學習筆記,如有錯誤請提出。

在通常的情況下,我們在Activity中有一個View,我們要獲得這個View的執行個體是要通過findViewById這個方法,然後這個方法返回的是一個Object類型,我們還需要進行強制的類型轉換,但是相信很多人都遇到過,當我們的一個布局中有很多個控制項的時候,每一個控制項都要進行上面的這個操作其實是很煩躁的,特別是強制類型轉換,即使是用Alt+Enter,多按幾次都累了。而今天要用的是通過註解的方式來簡化這一個複雜的步驟,在我們編寫好相應的代碼之後,擷取執行個體的方法就變成像下面這樣簡單了

@ViewInject(R.id.buy)private Button buy;

通過上面這兩行簡單的代碼,就能把id所對應的View執行個體化了,下面我們一步一步的來學習如何使用註解。

先說原理,我們都要知道,在Java中,通過反射,我們可以知道每一個類的詳細資料,比如有什麼欄位,有什麼方法,類名等等,我們通過註解和反射配合,使用反射調用類中的方法,然後讀取註解的參數來進行方法的執行。簡單的說,就是其實我們還是會調用findViewById這個方法,但是,這個方法可以放到工具類中執行了,我們只需要像上面那樣給出參數就行了。

先說下反射,反射就是允許我們動態操作一個類,擷取類的欄位,執行類的方法,擷取類的名字等等,在這裡我們一般會用到下面的這幾個方法:

getMethod:擷取類中的public方法

getDeclaredMethod:擷取類中的所有方法

getField:擷取類中的public欄位(屬性)

getDeclaredField:擷取類中的所有欄位

還有其他的請自行參考Class類的源碼

 

再說註解,我們看到的最多的註解擷取是@Override,當我們重寫父類中的方法的時候,這個註解會被編譯器自動產生出來,這個註解只是表明方法是重寫了父類方法。

那麼我們究竟該如何自訂我們想要的註解呢?其實很簡單,直接看代碼:

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface  ViewInject{    int value();}

@Target的意思是我們註解作用的目標,這裡是ElementType.FIELD,也就是作用於欄位的

 ElementType的類型有以下幾種:

   1.CONSTRUCTOR:用於描述構造器
 2.FIELD:用於描述欄位
 3.LOCAL_VARIABLE:用於描述局部變數
 4.METHOD:用於描述方法
 5.PACKAGE:用於描述包
 6.PARAMETER:用於描述參數
 7.TYPE:用於描述類、介面(包括註解類型) 或enum聲明

@Retention的意思是註解的運行層級

  RetentionPolicy的類型有以下幾種

   1.SOURCE:在源檔案中有效(即源檔案保留)
 2.CLASS:在class檔案中有效(即class保留)
 3.RUNTIME:在運行時有效(即運行時保留)

@interface則是表明這個類是一個註解,@號不能漏掉,否則變成了介面了

如果想對註解瞭解得更多,可以參考:http://www.cnblogs.com/gmq-sh/p/4798194.html 這篇博文,很詳細,對於我們想要的功能,以上的內容就足夠了

定義好了註解,如果我們直接來使用,是沒有任何效果的,因為註解只是一段代碼,並沒有關聯上我們的控制項,所以我們要編寫一個工具類來做關聯

public class AnnotateUtils {    public static void injectViews(Activity activity) {        Class<? extends Activity> object = activity.getClass(); // 擷取activity的Class        Field[] fields = object.getDeclaredFields(); // 通過Class擷取activity的所有欄位        for (Field field : fields) { // 遍曆所有欄位            // 擷取欄位的註解,如果沒有ViewInject註解,則返回null            ViewInject viewInject = field.getAnnotation(ViewInject.class);             if (viewInject != null) {                int viewId = viewInject.value(); // 擷取欄位註解的參數,這就是我們傳進去控制項Id                if (viewId != -1) {                    try {                        // 擷取類中的findViewById方法,參數為int                        Method method = object.getMethod("findViewById", int.class);                        // 執行該方法,返回一個Object類型的View執行個體                        Object resView = method.invoke(activity, viewId);                        field.setAccessible(true);                        // 把欄位的值設定為該View的執行個體                        field.set(activity, resView);                    } catch (NoSuchMethodException e) {                        e.printStackTrace();                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    } catch (InvocationTargetException e) {                        e.printStackTrace();                    }                }            }        }    }}

在工具類中,我們擷取到了activity的Class,接著獲得類中的所有欄位,遍曆欄位,如果有ViewInject註解,則擷取註解的中的值,通過擷取並執行類中的方法(findViewById)來獲得對應View的執行個體,最後把執行個體賦值給當前的欄位,整個過程就完成了。

當我們需要使用註解的時候,我們只需要在定義View的時候,在View的欄位上添加對應的註解,把Id傳入,然後在onCreate方法中調用上面這個工具類的方法即可。

@ViewInject(R.id.buy)private Button buy;@ViewInject(R.id.money)private TextView money;@ViewInject(R.id.tv_power)private TextView power;@ViewInject(R.id.tv_life)private TextView life;@ViewInject(R.id.tv_dex)private TextView dex;
@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    AnnotateUtils.injectViews(this);}

 

最後,有幾點說明:

①如果註解中的值不是value,那麼在進行註解是時候,需要給出對應的值的名字,假如我們在註解中做了如下定義:

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface  ViewInject{    int id();}

那麼在註解的時候,需要這樣:

@ViewInject(id = R.id.buy)private Button buy;

因為value這個名字是預設的,如果我們定義為value,那麼註解的時候可以省略

②註解還可以幫我們注入布局,設定監聽等,如果有興趣,可以繼續探討下去

③使用註解的時候,句末不能加“;”

 

Android開發學習之路-讓註解幫你簡化代碼,徹底拋棄findViewById

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.