Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 注解的一些應用以及原理

Android 注解的一些應用以及原理

編輯:關於Android編程

在這邊文章之前你首先需要對java 的注解部分有一個基本的了解(不需要太過的深入)。   簡單來說,注解這個東西就是用於輔助我們開發java代碼的,注解本身無法干擾java源代碼的執行。   在android 裡面 注解主要用來干這麼幾件事:   1.和編譯器一起給你一些提示警告信息。   2.配合一些ide 可以更加方便快捷 安全有效的編寫java代碼。谷歌出的support-annotations這個庫 就是主要干這個的。   3.和反射一起 提供一些類似於spring 可配置的功能,方便簡潔(這部分有過j2ee 開發經驗的可以直接跳過了)。       首先來看一下官方提供的庫吧。首先在build文件裡 增加一句話   compile 'com.android.support:support-annotations:22.2.0'   這個地方要注意,我現在是取得version22.2的版本,你們引用的時候如果有更新,android studio可能會提示你sync失敗,這個時候你要自己去谷歌官網查詢一下最新的版本號自己替換。   然後我們就可以看看這個谷歌的注解庫 為我們提供了哪些功能。       首先來看 Nullness 注解 這個主要是有兩種@Nullable  和 @NonNull。   前者表示可以為空 後者表示不能為空。   我只演示後者(前者可以自己測試)定義一個函數       然後我們去調用他 看看。   1  String a=null; 2         sayHello(a);     這個時候IDE就自動會給我們警告信息了(其實ide 的警告信息多數也是從編譯器而來)    
1 Argument 'a' might be null less... (Ctrl+F1) 
2 This inspection analyzes method control and data flow to report possible conditions that are always true or false, expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.
3 Variables, method parameters and return values marked as @Nullable or @NotNull are treated as nullable (or not-null, respectively) and used during the analysis to check nullability contracts, e.g. report possible NullPointerException errors.
4 More complex contracts can be defined using @Contract annotation, for example:
5 @Contract("_, null -> null") — method returns null if its second argument is null @Contract("_, null -> null; _, !null -> !null") — method returns null if its second argument is null and not-null otherwise @Contract("true -> fail") — a typical assertFalse method which throws an exception if true is passed to it 
6 The inspection can be configured to use custom @Nullable
7 @NotNull annotations (by default the ones from annotations.jar will be used)

 

    再介紹一下   Resource Type Annotations 定義一個方法   1  private String sayHello(@StringRes int resId) { 2         return ""; 3     } 然後調用   1         sayHello(R.layout.activity_main); 這個地方這個注解的意思是你只能傳string 類型的id進去 而我們傳了layout類型的,如果你不加那個注解的話 ide和編譯器是沒有反應的,到運行期才會有錯誤。   但是你加了以後就會發現       IDE也是直接報錯的!       再比如這樣一段代碼  
 1  class TestAnoataion {
 2 
 3         public void testAnoation() {
 4             Log.v("main", "test anoation");
 5         }
 6     }
 7 
 8     class TestAnoataion2 extends TestAnoataion
 9     {
10         public void testAnoation()
11         {
12 
13         }
14     }

 

    假使我們父類的設計的時候本意是 如果你要重寫testAnoation這個方法一定得調用父類的testAnation這個方法。就跟我們activity的oncreate方法一樣。   哪如果子類沒有寫super.testAnoation的話 你根本就不知道 就很容易報錯。但是如果你加了注解。那麼ide就會很明確的提示你錯誤       是不是很強大?當你調用了super語句以後 一切就和諧了!       那這個support庫 就暫時介紹到這裡,個人建議大家有時間一定要自己過一遍一個官方文檔。   這裡定義的注解 對提高大家的代碼質量 會非常非常有幫助。一定要掌握學會。       最後再上一個小例子吧,很多android 開發者都喜歡依賴注入的一些開源庫,來綁定你的控件id。   這樣寫法不但優雅而且好用。   Butterknife 這個開源庫大家一定很多人都用過,我就寫一個小demo 來演示一下這些庫的原理,其實還蠻簡單的。   需要注意的是 要理解這個小demo 需要你除了知道注解的基礎知識以外還需要有反射的基礎知識。   關於反射我很久之前也寫過一個教程   http://www.cnblogs.com/punkisnotdead/p/3384464.html   不會的可以趕緊補一下。   首先定義一個InjectView注解    
 1 package com.example.administrator.testfab;
 2 
 3 import java.lang.annotation.ElementType;
 4 import java.lang.annotation.Retention;
 5 import java.lang.annotation.RetentionPolicy;
 6 import java.lang.annotation.Target;
 7 
 8 /**
 9  * Created by Administrator on 2015/8/5.
10  */
11 
12 @Target(ElementType.FIELD)
13 @Retention(RetentionPolicy.RUNTIME)
14 public @interface InjectView {
15     //id就表示哪些控件,-1就表示取不到時候的默認值
16     int id() default -1;
17 }
 

 

  然後定義一個解釋器    
 1 package com.example.administrator.testfab;
 2 
 3 import android.app.Activity;
 4 import android.view.View;
 5 
 6 import java.lang.reflect.Field;
 7 
 8 /**
 9  * Created by Administrator on 2015/8/5.
10  */
11 public class InjectViewParser {
12 
13     public static void inject(Object object) {
14 
15         try {
16             parse(object);
17         } catch (Exception e) {
18             e.printStackTrace();
19         }
20     }
21 
22     public static void parse(Object object) throws Exception {
23         final Class<?> clazz = object.getClass();
24         View view = null;
25         Field[] fields = clazz.getDeclaredFields();
26         for (Field field : fields) {
27             if (field.isAnnotationPresent(InjectView.class)) {
28                 InjectView injectView = field.getAnnotation(InjectView.class);
29                 int id = injectView.id();
30                 if (id < 0) {
31                     throw new Exception("id must not be null");
32                 } else {
33                     field.setAccessible(true);
34                     if (object instanceof View) {
35                         view = ((View) object).findViewById(id);
36                     } else if (object instanceof Activity) {
37                         view = ((Activity) object).findViewById(id);
38                     }
39                     field.set(object, view);
40                 }
41 
42             }
43 
44         }
45 
46     }
47 }
 

 

  最後在actity裡使用即可  
 1 package com.example.administrator.testfab;
 2 
 3 import android.os.AsyncTask;
 4 import android.os.Bundle;
 5 import android.support.annotation.CallSuper;
 6 import android.support.annotation.NonNull;
 7 import android.support.annotation.Nullable;
 8 import android.support.annotation.StringRes;
 9 import android.support.v7.app.AppCompatActivity;
10 import android.util.Log;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.widget.Button;
14 
15 public class MainActivity extends AppCompatActivity {
16 
17     @InjectView(id = R.id.bt)
18     private Button bt;
19 
20 
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_main);
25         //開始注入
26         InjectViewParser.inject(this);
27         //這個主要是測試注入id 成功沒有 成功了就不會報錯~
28         bt.setText("inject done");
29 
30 
31     }
32 
33 
34     @Override
35     public boolean onCreateOptionsMenu(Menu menu) {
36         // Inflate the menu; this adds items to the action bar if it is present.
37         getMenuInflater().inflate(R.menu.menu_main, menu);
38         return true;
39     }
40 
41     @Override
42     public boolean onOptionsItemSelected(MenuItem item) {
43         // Handle action bar item clicks here. The action bar will
44         // automatically handle clicks on the Home/Up button, so long
45         // as you specify a parent activity in AndroidManifest.xml.
46         int id = item.getItemId();
47 
48         //noinspection SimplifiableIfStatement
49         if (id == R.id.action_settings) {
50             return true;
51         }
52 
53         return super.onOptionsItemSelected(item);
54     }
55 
56 
57 
58 }

 

   

 

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved