Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android用法知識點

Android用法知識點

編輯:關於Android編程

1.引言
從JDK1.5開始,引入了注解類Annotation,Annotation其實是一種接口,可以作用於類、方法、屬性等等 ,它可以通過反射機制來訪問annotation信息,獲取所加上注解信息,做相應的操作。相當於給相關的作用對象打上“tag”,使用方便,作用廣泛。
2.java.lang中的注解
在java.lang中,用到三種注解類,即常用到的Deprecated,Override和SuppressWarnings.
2.1 @Deprecated 過時
在使用Eclipse或AS編寫程序過程中,有一些方法編寫出來之後被畫上了中劃線,表示該方法已過時,建議使用新的一些方法代替。
如:viewPager.setOnPageChangeListener()方法在安卓API23中已過時,在源代碼中的該方法上赫然多了一個注解@Deprecated,可使用addOnPageChangeListener()方法代替。
如果使用javac命令編譯,會彈出:”注意:使用或覆蓋了已過時的API“
2.2 @Override 復寫
這是開發過程中最常遇到的注解了,表示復寫父類中的方法。如果方法上有這條注解但沒有重寫父類方法,則會生成一條錯誤消息。這個注解有效地保證了方法一定會被復寫。比如開發過程中,手動在子類中復寫父類方法,只正確寫出了方法名稱,未寫正確方法的參數,則相當於方法的重載,並不是復寫。這種問題如果在功能上有錯誤產生,在檢查過程中是很難找到的。使用@Override注解,有效地表明,此方法是復寫父類的方法,不會產生手動的錯誤問題。
2.3 @SuppressWarnings 阻止警告
阻止了彈出的警告,比如屏蔽對上述過時的提示,可在調用setOnPageChangeListener()方法之上加上@SuppressWarnings("deprecation"),這樣雖然在IDE中仍以中劃線的形式表示,但如果使用javac命令就不再提示警告。
3.元注解
那麼以上的注解類的源碼又是什麼樣的呢,打開Override發現其代碼如下:
[java] view plain copy

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
這裡可以發現注解類的定義方法以及注解類上所加的注解——元注解。元注解有四個,位於java.lang.annotation包中:Documented,Inherited,Retention,Target
3.1@Target
表示注解作用的目標。
[java] view plain copy

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
注解可以作用的目標由枚舉類ElementType決定,可作用於類、方法、屬性等,數組表示注解可以有多個作用域。
[java] view plain copy

public enum ElementType {
TYPE,// 類、接口、注解類型或枚舉
FIELD, //屬性
METHOD, //方法
PARAMETER,// 用於描述參數
CONSTRUCTOR,//構造方法
LOCAL_VARIABLE,//局部變量
ANNOTATION_TYPE,//注解類
PACKAGE //包
}
注解作用於類時,定義@Target(ElementType.TYPE),ElementType .TYPE表示類型,Class,Interface等都實現了java中的Type接口,因此ElementType.TYPE 表示注解作用於這些"類"(並不是單純的Class類)

3.2@Retention
表示注解的作用時段
[java] view plain copy
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
由此可見,Retention定義的是RetentionPolicy類型的數據,RetentionPolicy是一個枚舉類型,包括SOURCE,CLASS,RUNTIME三個類型。表示注解保留的階段。
SOURCE:表示注解只在源文件中保留
CLASS:表示注解保留到.class文件中
RUNTIME:表示注解一直保留到內存中,類加載器把.class文件加載到內存中產生的字節碼中要保留注解信息。
可想而知,@Override僅在寫代碼時用到,其Retention中的值為RetentionPolicy.SOURCE,@SuppressWarnings也只是編譯器使用的,保留到SOURCE階段。而@Deprecated在內存中也需要保留,編譯器需要得知方法是否過時,從加載到內存中的二進制文件中獲取,因而要保留到RUNTIME階段

3.3@Documented
注解只是一個標記的話,那麼使用javadoc生成文檔時,這些注解都不會存在於文檔中,要使注解在文檔中也存在,就可以在使用了注解的作用對象上加上@Documented這個注解。javadoc所生成的文檔就會帶上注解信息。

3.4@Inherited
該注解表示子類可以集成加載父類上的注解。但要注意:
1.注解定義在類上面,子類是可以繼承該注解
2.注解定義在方法上面,子類也可以繼承該注解,但是如果子類復寫了父類中定義了注解的方法,那麼子類將無法繼承該方法的注解,也就是說,子類在復寫父類中被@Inherited標注的方法時,會將該方法上面的注解覆蓋掉
3.Interface的實現類(implements實現)無法繼承接口中所定義的被@Inherited標注的注解
4.注解的參數
在注解後為注解增加參數,如上述的@Retention、@Target後的括號中就是注解的參數。
參數的類型,支持基本數據類型、String類型、Class類型、enum類型、Annotation類型以及上述所有類型的數組。
當注解只有一個參數時,可以用value作為參數名稱,在使用參數時,只用在括號中寫參數的值而不用寫參數名稱。若存在多個參數時,需寫上對應的參數名,並賦值,如@Subscribe(tag="xx"),若參數為數組類型,則需賦值形如:@Target({ElementType.TYPE,ElementType.METHOD})
5.自定義注解
從上面的注解中,也大致看到了注解的定義方式。
1.使用@interface定義一個注解類,其內部自行繼承了Annotation類。
2.在該類中定義注解的參數,定義方式很像方法。
3.注解元素必須有確定的值,要麼在定義注解的默認值中指定,要麼在使用注解時指定,非基本類型的注解元素的值不可為null。因此, 使用空字符串或0作為默認值是一種常用的做法。定義一些特殊的值,例如空字符串或者負數,表示某個元素不存在參數設置默認值時,後面跟上default即可設置默認值。
4.當注解的參數只有一個時,建議用value作為參數名,這樣在使用注解時,可以直接寫參數的值
接下來自定義一個注解類:
[java] view plain copy

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Car{
String name() default "";
int number() default -1;
}
再定義一個類去使用這個注解:
[java] view plain copy

@Car(name="好車",number=666)
public class CarBMW(){

}
那麼如何獲取這些注解值呢?有如下的方法:
[java] view plain copy

if(CarBMW.class.isAnnotationPresent(Car.class)){//判斷CarBMW類是否有注解類Car
Car carAnnotation=(Car)CarBMW.class.getAnnotation(Car.class);//獲取注解實例對象
Log.v("Shawn",carAnnotation.name());//獲取name參數的值
Log.v("Shawn",carAnnotation.number());//獲取number參數的值
}
6.Android中的注解
6.1兩個常見的注解
Android從API16引入了annotation包,包括兩個注解@TargetApi和@SuppressLint
@TargetApi (Build.VERSION_CODES.XX)用於屏蔽某一新api中才能使用的方法報的lint檢查出現的錯誤。
@SuppressLint("NewApi") 屏蔽一切新api中才能使用的方法報的android lint錯誤

當然,這兩個注解的作用僅僅是屏蔽lint錯誤,在方法中還要判斷版本做不同的操作,比如:
[java] view plain copy

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XX) {
//高於XX版本進行的操作
} else {
//低於XX版本進行的操作
}
6.2Android中用到的注解
API19引入了很多注解,起初是以jar包形式引入的,放在SDK目錄下sdk\extras\android\m2repository\com\android\support\support-annotations\
在API21之後,直接放入了annotation包中
Android中的注解分為八類,在API23中有42個注解類

6.2.1 @CallSuper
要求方法必須調用父類方法,可想而知,Activity的onCreate()方法有此注解標識。
6.2.2 @NonNull和@Nullable
定義一個變量或對象可以為空或不可為空,用在方法上表示方法可否返回空。
6.2.3 資源類注解
@AnimatorRes,@AnimRes,@AnyRes,@ArrayRes,@AttrRes,@ BoolRes,@ ColorRes,@ DimensRes,@ DrawableRes,@ FractionRes,@ IdRes,@ IntegerRes,@ InterpolatorRes,@ LayoutRes,@ MenuRes,@ PluralsRes,@ RawRes,@ StringRes,@ StyleableRes,@StyleRes,@ TransitionRes,@ XmlRes
這部分注解是非常有實用性的,有22個,用法如:
[java] view plain copy

getDrawable(@DrawableRes int id) //getDrawable方法限定了傳入的參數必須是Drawable資源文件
另外還有個@ColorInt,限制傳入Hex顏色值。
在開發過程中需要傳入某種資源文件時,用此類注解,是很有限制作用的做法。
6.2.4@IdDef和@StringDef
提到最常用的Toast,在API21之前,一般可以這麼寫
Toast.makeText(context, "msg", 0).show();
但是21之後,0突然被劃紅線了,查看源碼發現,之前是這麼寫的:
[java] view plain copy
public static final int LENGTH_SHORT = 0;
public static final int LENGTH_LONG = 1;
makeText方法中單純地寫著int duration參數,而21之後,成了這樣:
[java] view plain copy
@IntDef({LENGTH_SHORT, LENGTH_LONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Duration {}
在makeText的duration參數之前加上了注解@Duration,這就要求傳入Duration中的值才不會報警告。
可以想象,@IntDef和@String Def中放入了一個value數組。
在開發中,這兩個注解就可以用來限制枚舉值了。

6.2.5 范圍約束@FloatRange、@IntRange和@Size
前兩個限制了數字的范圍,比如可以用來限制傳入參數值的范圍,
@Size可以用來限定集合的大小或者限定字符串的長度,還可以做其他限制:
1.限制最小最大數量:@Size(min=1,max=10 )
2.數量必須是2的倍數(偶數): @Size(multiple=2)

6.2.6 進程類注解
@UiThread,@BinderThread,@MainThread,@WorkerThread
用來限定方法或類在指定的線程類型中被調用,比如 AsyncTask中的方法就有如下的限定:
[java] view plain copy

@WorkerThread
protected abstract Result doInBackground(Params... params){
//doInBackground
}
@MainThread
protected void onProgressUpdate(Progress... values) {
//onProgressUpdate
}
6.2.7@CheckResult
該注解意味著需要對方法的返回值進行處理,例如:有個方法為
[java] view plain copy

@CheckResult
public boolean checkValid(String value){
return TextUtils.isEmpty(value);
}
當調用者直接調用checkValid("abc");時會報錯,這意味著,需要對方法的返回值進行處理,無論返回true或false,需要進行後續操作,不能單單調用一句checkValid("abc");

6.2.8 權限注解@RequiresPermission
如果方法的調用需要權限,可以加這個注解,當需要幾個權限中的一個時,使用anyOf,如 @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})
若需要多個權限,使用allOf,如 @RequiresPermission(allOf = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
若需要單獨的標注讀和寫的權限訪問,所以可以用@Read或者@Write標注每一個權限需求
6.2.9 @SdkConstant
表示一個常量字段應該被輸出在SDK工具中使用,例如:
添加一個自定義的Action:
[java] view plain copy
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MY_TEST = "android.intent.action.MY_TEST";
則可以這樣使用:
[java] view plain copy
Intent myTest = new Intent(Intent.ACTION_MY_TEST);
mContext.sendBroadcast(myTest);
6.2.10@Widget
用於類的注解,表示該類是自定義的Widget類

此外還有兩個注解即上述的@TargetApi和@SuppressLint不再贅述。
7.總結
綜上,注解部分就介紹完了。注解在開發過程中有很強的實用性,使用注解可以明確開發過程中的一些數據類型,還可以對一些數據進行限制,從而提高開發效率。

AIDL進程間通信的流程,分為服務端和客戶端:
1.服務端
首先需要創建一個Service用來監聽客戶端的連接請求,然後創建一個AIDL文件,將暴露給客戶端的接口在這個AIDL文件中聲明,最後在Service中實現這個AIDL接口即可。
2.客戶端
首先通過綁定服務端的Service,綁定成功後,將服務端返回的IBinder對象轉成AIDL接口所屬的類型。接著就可以調用AIDL中的方法了

使用AIDL實現IPC

使用AIDL實現IPC服務的步驟是:

1. 創建.aidl文件-該文件(YourInterface.aidl)定義了客戶端可用的方法和數據的接口。

2. 在makefile文件中加入.aidl文件-(Eclipse中的ADT插件提供管理功能)Android包括名為AIDL的編譯器,位於tools/文件夾。

3. 實現接口-AIDL編譯器從AIDL接口文件中利用Java語言創建接口,該接口有一個繼承的命名為Stub的內部抽象類(並且實現了一些IPC調用的附加方法),要做的就是創建一個繼承於YourInterface.Stub的類並且實現在.aidl文件中聲明的方法。

4. 向客戶端公開接口-如果是編寫服務,應該繼承Service並且重載Service.onBind(Intent) 以返回實現了接口的對象實例

創建.aidl文件
AIDL使用簡單的語法來聲明接口,描述其方法以及方法的參數和返回值。這些參數和返回值可以是任何類型,甚至是其他AIDL生成的接口。重要的是必須導入所有非內置類型,哪怕是這些類型是在與接口相同的包中。下面是AIDL能支持的數據類型:

1.Java編程語言的主要類型 (int, boolean等) — 不需要 import 語句。

2.以下的類 (不需要import 語句):
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved