Android自定義View構(gòu)造函數(shù)詳解
初始Custom View的構(gòu)造函數(shù)
之前寫過一篇實(shí)現(xiàn)圓形進(jìn)度條的博客(自定義圓形進(jìn)度條),通常我們在實(shí)現(xiàn)Custom View的時候,都會先繼承View并實(shí)現(xiàn)View的三個構(gòu)造函數(shù),例如:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
public class MyCustomView extends View {
/**
* 第一個構(gòu)造函數(shù)
*/
public MyCustomView(Context context) {
this(context, null);
}
/**
* 第二個構(gòu)造函數(shù)
*/
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 第三個構(gòu)造函數(shù)
*/
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO:獲取自定義屬性
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
網(wǎng)上有很多關(guān)于三個構(gòu)造函數(shù)使用時機(jī)的說法,但是說法正確的卻沒有幾家,這里正式的給大家科普一下:
在代碼中直接new一個Custom View實(shí)例的時候,會調(diào)用第一個構(gòu)造函數(shù).這個沒有任何爭議.
在xml布局文件中調(diào)用Custom View的時候,會調(diào)用第二個構(gòu)造函數(shù).這個也沒有爭議.
在xml布局文件中調(diào)用Custom View,并且Custom View標(biāo)簽中還有自定義屬性時,這里調(diào)用的還是第二個構(gòu)造函數(shù).
也就是說,系統(tǒng)默認(rèn)只會調(diào)用Custom View的前兩個構(gòu)造函數(shù),至于第三個構(gòu)造函數(shù)的調(diào)用,通常是我們自己在構(gòu)造函數(shù)中主動調(diào)用的(例如,在第二個構(gòu)造函數(shù)中調(diào)用第三個構(gòu)造函數(shù)).
至于自定義屬性的獲取,通常是在構(gòu)造函數(shù)中通過obtainStyledAttributes函數(shù)實(shí)現(xiàn)的.這里先介紹一下如何生成Custom View的自定義屬性.
生成Custom View的自定義屬性
Custom View添加自定義屬性主要是通過declare-styleable標(biāo)簽為其配置自定義屬性,具體做法是: 在res/values/目錄下增加一個resources xml文件,示例如下(res/values/attrs_my_custom_view.xml):
<resources> <declare-styleable name="MyCustomView"> <attr name="custom_attr1" format="string" /> <attr name="custom_attr2" format="string" /> <attr name="custom_attr3" format="string" /> <attr name="custom_attr4" format="string" /> </declare-styleable> <attr name="custom_attr5" format="string" /> </resources>
在上述xml文件中,我們聲明了一個自定義屬性集MyCustomView,其中包含了custom_attr1,custom_att2,custom_attr3,custom_attr4四個屬性.同時,我們還聲明了一個獨(dú)立的屬性custom_attr5.
所有resources文件中聲明的屬性都會在R.attr類中生成對應(yīng)的成員變量:
public final class R {
public static final class attr {
public static final int custom_attr1=0x7f010038;
public static final int custom_attr2=0x7f010039;
public static final int custom_attr3=0x7f01003a;
public static final int custom_attr4=0x7f01003b;
public static final int custom_attr5=0x7f010000;
}
}
但是聲明在標(biāo)簽中的屬性,系統(tǒng)還會在R.styleable類中生成相關(guān)的成員變量:
public static final class styleable {
public static final int[] MyCustomView = {
0x7f010038, 0x7f010039, 0x7f01003a, 0x7f01003b
};
public static final int MyCustomView_custom_attr1 = 0;
public static final int MyCustomView_custom_attr2 = 1;
public static final int MyCustomView_custom_attr3 = 2;
public static final int MyCustomView_custom_attr4 = 3;
}
可以看出,R.styleable.MyCustomView是一個數(shù)組,其中的元素值恰好就是R.attr.custom_attr1~R.attr.custom_attr4的值.而下面的MyCustomView_custom_attr1~MyCustomView_custom_attr4正好就是其對應(yīng)的索引.
知道了這些之后,我們就可以來學(xué)習(xí)一下,如何在Custom View的構(gòu)造函數(shù)中獲取自定義屬性的值了.
在Custom View的構(gòu)造函數(shù)中獲取自定義屬性
在第三個構(gòu)造函數(shù)中獲取自定義屬性的代碼如下:
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);
Log.e("customview", "attr1=" + attr1);
Log.e("customview", "attr2=" + attr2);
Log.e("customview", "attr3=" + attr3);
Log.e("customview", "attr4=" + attr4);
ta.recycle();
}
關(guān)于自定義屬性的獲取,我們主要是調(diào)用了context.obtainStyledAttributes這個函數(shù),相信這個函數(shù)大家自定義View的時候都用的很熟練了.我們來看一下這個函數(shù)的源碼實(shí)現(xiàn):
public final TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs) {
return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
}
通過對源碼的追蹤,我們發(fā)現(xiàn)context的兩個參數(shù)的obtainStyledAttributes方法最終是調(diào)用了Theme的4個參數(shù)的obtainStyledAttributes方法.我們來看一下這個函數(shù)的源碼實(shí)現(xiàn):
public TypedArray obtainStyledAttributes(AttributeSet set,
@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
final int len = attrs.length;
final TypedArray array = TypedArray.obtain(Resources.this, len);
// XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse
// out the attributes from the XML file (applying type information
// contained in the resources and such).
final XmlBlock.Parser parser = (XmlBlock.Parser)set;
AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
parser != null ? parser.mParseState : 0, attrs, array.mData, array.mIndices);
array.mTheme = this;
array.mXml = parser;
if (false) {
int[] data = array.mData;
System.out.println("Attributes:");
String s = " Attrs:";
int i;
for (i=0; i<set.getAttributeCount(); i++) {
s = s + " " + set.getAttributeName(i);
int id = set.getAttributeNameResource(i);
if (id != 0) {
s = s + "(0x" + Integer.toHexString(id) + ")";
}
s = s + "=" + set.getAttributeValue(i);
}
System.out.println(s);
s = " Found:";
TypedValue value = new TypedValue();
for (i=0; i<attrs.length; i++) {
int d = i*AssetManager.STYLE_NUM_ENTRIES;
value.type = data[d+AssetManager.STYLE_TYPE];
value.data = data[d+AssetManager.STYLE_DATA];
value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
s = s + " 0x" + Integer.toHexString(attrs[i])
+ "=" + value;
}
System.out.println(s);
}
return array;
}
這里就不做過多的源碼講解,而是把這四個參數(shù)的含義解釋給大家:
AttributeSet set: 屬性值的集合.
int[] attrs: 我們自定義屬性集合在R類中生成的int型數(shù)組.這個數(shù)組中包含了自定義屬性的資源ID.
int defStyleAttr: 這是當(dāng)前Theme中的包含的一個指向style的引用.當(dāng)我們沒有給自定義View設(shè)置declare-styleable資源集合時,默認(rèn)從這個集合里面查找布局文件中配置屬性值.傳入0表示不像該defStyleAttr中查找默認(rèn)值.
int defStyleRes: 這個也是一個指向Style的資源ID,但是僅在defStyleAttr為0或者defStyleAttr不為0但Theme中沒有為defStyleAttr屬性賦值時起作用.
由于一個屬性可以在很多地方對其進(jìn)行賦值,包括: XML布局文件中、decalare-styleable、theme中等,它們之間是有優(yōu)先級次序的,按照優(yōu)先級從高到低排序如下:
屬性賦值優(yōu)先級次序表:
在布局xml中直接定義 > 在布局xml中通過style定義 > 自定義View所在的Activity的Theme中指定style引用 > 構(gòu)造函數(shù)中defStyleRes指定的默認(rèn)值
為了讓大家有更清楚更直觀的了解,再接下來設(shè)置自定義屬性的章節(jié)中,我將對custom_attr1~4這4個屬性分別在上述四個地方進(jìn)行定義,然后在Custom View的構(gòu)造函數(shù)中獲取它的值,從而看一下,優(yōu)先級順序是否和我們預(yù)期的一樣.
設(shè)置自定義屬性值
以下的第幾個參數(shù)均是針對Resources.Theme類的obtainStyledAttributes四參數(shù)構(gòu)造方法來說明的.
第二個參數(shù)——在布局xml文件中為屬性賦值
在設(shè)置自定義屬性之前,我們首先要在主Activity的布局文件中調(diào)用我們的Custom View,并且為其設(shè)置特定的屬性.
主布局文件內(nèi)容如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <com.kevintan.eventbussample.view.MyCustomView android:id="@+id/id_custom_view" android:layout_width="400dp" android:layout_height="400dp" custom:custom_attr1="attr1_xml" style="@style/TestCustomView"/> </FrameLayout>
示例結(jié)果:
05-28 17:19:56.542 23575-23575/? E/customview: attr1=attr1_xml
05-28 17:19:56.542 23575-23575/? E/customview: attr2=null
05-28 17:19:56.542 23575-23575/? E/customview: attr3=null
05-28 17:19:56.542 23575-23575/? E/customview: attr4=null
注意:
在給自定義屬性賦值時,首先需要增加自定義屬性的命名空間,例如: xmlns:custom=”http://schemas.Android.com/apk/res-auto”,Android Studio推薦使用res-auto,在Eclipse中需要使用Custom View所在的包名: xmlns:cv=”http://schemas.android.com/apk/com.kevintan.eventbussample.view”
這里,在布局文件中我們?yōu)閏ustom_attr1賦值為: attr1_xml.自定義View中獲取該屬性值對應(yīng)了getTheme().obtainStyledAttributes方法中的第二個參數(shù)@StyleableRes int[] attrs
第二個參數(shù)——在style中為屬性賦值
其次,自定義屬性還可以在Style中進(jìn)行賦值.
首先,我們在xml布局文件中還為MyCustomView增加一個自定義的style,style代碼如下:
<style name="TestCustomView"> <item name="custom_attr1">attr1_style</item> <item name="custom_attr2">attr2_style</item> </style>
然后,我們修改布局文件,增加style字段:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <com.kevintan.eventbussample.view.MyCustomView android:id="@+id/id_custom_view" android:layout_width="400dp" android:layout_height="400dp" custom:custom_attr1="attr1_xml" style="@style/TestCustomView"/> </FrameLayout>
示例結(jié)果:
05-28 17:19:56.542 23575-23575/? E/customview: attr1=attr1_xml
05-28 17:19:56.542 23575-23575/? E/customview: attr2=attr2_style
05-28 17:19:56.542 23575-23575/? E/customview: attr3=null
05-28 17:19:56.542 23575-23575/? E/customview: attr4=null
這里我們再次對custom_attr1屬性進(jìn)行了賦值,同時我們對custom_attr2也進(jìn)行了賦值.
小提示:
聰明的同學(xué)肯定都猜到我這樣賦值的作用了,但是還是要簡述一下:
對于custom_attr1,我們在xml布局文件、style、defStyle和theme中均進(jìn)行賦值,那最終得到的結(jié)果必然能證實(shí)誰的優(yōu)先級最高.
對于custom_attr2,我們在style、defStyle和theme中進(jìn)行賦值,通過得到的結(jié)果我們能知道誰的優(yōu)先級第二高.
對于custom_attr3和custom_attr4的賦值情況我就不多解釋了,我相信大家都懂得??!
同時,還需要大家注意的是,只要是layout布局文件中,無論是通過namespace直接為屬性賦值,還是通過style為屬性賦值,在構(gòu)造函數(shù)獲取時都對應(yīng)了getTheme().obtainStyledAttributes方法中的第二個參數(shù)@StyleableRes int[] attrs
第三個參數(shù)defStyleAttr
這個參數(shù)的意思是:
原文: An attribute in the current theme that contains areference to a style resource that supplies defaults values for the TypedArray. Can be 0 to not look for defaults.
翻譯: 這是當(dāng)前Theme中的包含的一個指向style的引用.當(dāng)我們沒有給自定義View設(shè)置declare-styleable資源集合時,默認(rèn)從這個集合里面查找布局文件中配置屬性值.傳入0表示不向該defStyleAttr中查找默認(rèn)值.
為了測試該參數(shù)的作用和優(yōu)先級,我們需要進(jìn)行如下操作.
首先, 我們先聲明一個refrence格式的屬性, 用于表示style的引用.聲明在之前的res/values/attrs_my_custom_view.xml文件里即可:
<attr name="MyCustomViewDefStyleAttr" format="reference"/>
然后,需要到AndroidManifest.xml中查看包含該自定義View的Activity所使用的主題是:
<activity> android:name="com.kevintan.eventbussample.MainActivity" android:theme="@style/AppTheme" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
最后,在style.xml中的AppTheme主題下增加MyCustomViewDefStyleAttr的引用實(shí)現(xiàn).
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="MyCustomViewDefStyleAttr">@style/MyCustomViewDefStyleAttrImpl</item> </style> <style name="MyCustomViewDefStyleAttrImpl"> <item name="custom_attr1">attr1_defStyleAttr</item> <item name="custom_attr2">attr2_defStyleAttr</item> <item name="custom_attr3">attr3_defStyleAttr</item> </style>
代碼驗(yàn)證,記住如果要使用obtainStyledAttributes方法的第三個參數(shù), 就需要在第三個構(gòu)造函數(shù)中顯示的調(diào)用getTheme()的obtainStyledAttributes方法.
public MyCustomView(Context context, AttributeSet attrs) {
// 為defStyleAttr進(jìn)行賦值
this(context, attrs, R.attr.MyCustomViewDefStyleAttr);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, 0);
String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);
Log.e("customview", "attr1=" + attr1);
Log.e("customview", "attr2=" + attr2);
Log.e("customview", "attr3=" + attr3);
Log.e("customview", "attr4=" + attr4);
ta.recycle();
}
代碼中,有兩點(diǎn)需要大家注意:
我在第二個構(gòu)造參數(shù)中已經(jīng)對defStyleAttr進(jìn)行了賦值,第三個構(gòu)造參數(shù)直接使用傳入?yún)?shù)即可.
第三個構(gòu)造參數(shù)中,我使用了getTheme()的obtainStyledAttributes方法來代替context的2個參數(shù)的obtainStyledAttributes構(gòu)造方法.
示例結(jié)果:
05-28 17:19:56.542 23575-23575/? E/customview: attr1=attr1_xml
05-28 17:19:56.542 23575-23575/? E/customview: attr2=attr2_style
05-28 17:19:56.542 23575-23575/? E/customview: attr3=attr3_defStyleAttr
05-28 17:19:56.542 23575-23575/? E/customview: attr4=null
從結(jié)果可以看出,在主題中指定style引用的優(yōu)先級是低于在xml中直接賦值和使用style字段的.
同時,我們還需要了解一點(diǎn):
在Android系統(tǒng)中的控件,很多都在構(gòu)造參數(shù)中使用了第三個參數(shù),例如Button.這樣做的好處是: 當(dāng)我們切換不同的主題時,Button的樣式也能隨之進(jìn)行改變.
第四個參數(shù)——通過defStyleRes為屬性賦值
這個參數(shù)的意思是:
原文: A resource identifier of a style resource that supplies default values for the TypedArray, used only if defStyleAttr is 0 or can not be found in the theme. Can be 0 to not look for defaults.
翻譯: 這是一個指向Style的資源ID,但是僅在defStyleAttr為0或者defStyleAttr不為0但Theme中沒有為defStyleAttr屬性賦值時起作用.
通過翻譯,我們可以明確兩點(diǎn):
1.defStyleRes: 指向一個style引用.
2.defStyleRes的優(yōu)先級低于defStyleAttr.
為了驗(yàn)證,我們先在theme.xml文件中定義一個style:
<style name="MyCustomViewDefStyleRes"> <item name="custom_attr1">attr1_defStyleRes</item> <item name="custom_attr2">attr2_defStyleRes</item> <item name="custom_attr3">attr3_defStyleRes</item> <item name="custom_attr4">attr4_defStyleRes</item> </style>
然后,我們在自定義View的第三個構(gòu)造函數(shù)中的obtainStyledAttributes函數(shù)中進(jìn)行賦值,具體方法如下:
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.MyCustomViewDefStyleAttr);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 為defStyleRes進(jìn)行賦值
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, R.style.MyCustomViewDefStyleRes);
String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);
Log.e("customview", "attr1=" + attr1);
Log.e("customview", "attr2=" + attr2);
Log.e("customview", "attr3=" + attr3);
Log.e("customview", "attr4=" + attr4);
ta.recycle();
}
測試結(jié)果:
05-28 17:44:09.282 3137-3137/? E/customview: attr1=attr1_xml
05-28 17:44:09.282 3137-3137/? E/customview: attr2=attr2_style
05-28 17:44:09.282 3137-3137/? E/customview: attr3=attr3_defStyleAttr
05-28 17:44:09.282 3137-3137/? E/customview: attr4=null
重點(diǎn):
如果大家認(rèn)真的看實(shí)驗(yàn)結(jié)果,肯定會被上面的結(jié)果感到奇怪,明明指定了defStyleRes,為什么attr4的值還是null?
是因?yàn)橹爸v過defStyleRes的使用優(yōu)先級:只有當(dāng)defStyleAttr為0或者當(dāng)前Theme中沒有給defStyleAttr屬性賦值時才起作用.
所以,這里我們需要修改構(gòu)造函數(shù),將defStyleAttr設(shè)置為0.
public MyCustomView(Context context, AttributeSet attrs) {
// 為了驗(yàn)證defStyleRes的作用,將defStyleAttr設(shè)置為0
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyleAttr, R.style.MyCustomViewDefStyleRes);
String attr1 = ta.getString(R.styleable.MyCustomView_custom_attr1);
String attr2 = ta.getString(R.styleable.MyCustomView_custom_attr2);
String attr3 = ta.getString(R.styleable.MyCustomView_custom_attr3);
String attr4 = ta.getString(R.styleable.MyCustomView_custom_attr4);
Log.e("customview", "attr1=" + attr1);
Log.e("customview", "attr2=" + attr2);
Log.e("customview", "attr3=" + attr3);
Log.e("customview", "attr4=" + attr4);
ta.recycle();
}
最終結(jié)果:
05-28 17:49:03.707 5772-5772/? E/customview: attr1=attr1_xml
05-28 17:49:03.707 5772-5772/? E/customview: attr2=attr2_style
05-28 17:49:03.707 5772-5772/? E/customview: attr3=attr3_defStyleRes
05-28 17:49:03.707 5772-5772/? E/customview: attr4=attr4_defStyleRes
后記
在文章結(jié)尾, 我們再次總結(jié)一下自定義屬性的屬性賦值優(yōu)先級:
在布局xml中直接定義 > 在布局xml中通過style定義 > 自定義View所在的Activity的Theme中指定style引用 > 構(gòu)造函數(shù)中defStyleRes指定的默認(rèn)值.
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android studio 運(yùn)行main 函數(shù)的方法
- 詳解Android應(yīng)用main函數(shù)的調(diào)用
- Android Studio生成函數(shù)注釋的實(shí)現(xiàn)方法
- Android自定義View的三個構(gòu)造函數(shù)
- Android編程計算函數(shù)時間戳的相關(guān)方法總結(jié)
- Android自定義view 你所需要知道的基本函數(shù)總結(jié)
- Android 自定義View的構(gòu)造函數(shù)詳細(xì)介紹
- Android編程之匿名內(nèi)部類與回調(diào)函數(shù)用法分析
- Android Chronometer控件實(shí)現(xiàn)計時器函數(shù)詳解
- Android nativePollOnce函數(shù)解析
相關(guān)文章
Android實(shí)現(xiàn)截屏方式整理(總結(jié))
本篇文章主要介紹了Android 截屏方式整理(總結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Android UI實(shí)現(xiàn)廣告Banner輪播效果
這篇文章主要為大家詳細(xì)介紹了Android UI實(shí)現(xiàn)廣告Banner輪播效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12
如何為RecyclerView添加Header和Footer
這篇文章主要為大家詳細(xì)介紹了如何為RecyclerView添加Header和Footer,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12
Android 通過當(dāng)前經(jīng)緯度獲得城市的實(shí)例代碼
Android 通過當(dāng)前經(jīng)緯度獲得城市的實(shí)例代碼,需要的朋友可以參考一下2013-06-06
Android 中 viewpager 滑動指示器的實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了android 中 viewpager 滑動指示器,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-12-12
Android懸浮對話框(即點(diǎn)即關(guān)對話框)實(shí)現(xiàn)代碼
本文給大家介紹android懸浮對話框和即點(diǎn)即關(guān)閉對話框,本文介紹非常詳細(xì),具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-03-03
基于linux與windows平臺下 如何下載android sdk源代碼的方法詳解
本文主要是介紹在linux和windows平臺下,如何下載android sdk的源代碼,注意是sdk的源代碼,而不是android的所有源代碼,同時介紹如何把sdk源代碼加入到eclipse里,使android 平臺手機(jī)開發(fā)者可以直接查看源代碼,通過閱讀SDK源碼,能更好的理解和運(yùn)用Android的API2013-05-05

