Android技術體系結構
一、Android技術體系結構
1.Android項目目錄結構
src 源文件
gen ADT自動生成的JAVA文件,程序員千萬不要去修改
Android 4.2.2+Android Private Libraries jar文件
assets 資源文件,圖片,音頻,視頻等
bin 二進制文件,編譯過后的文件
libs 第三方的jar文件,即引用第三方的代碼
res 也是資源文件,與assets不同,生成的文件都有ID
├ drawable-hdpi 高分辨率圖片,我們要為不同分辨率準備不同的圖片。
├ drawable-ldpi 低分辨率圖片
├ drawable-mdpi 中分辨率圖片
├ drawable-xhdpi 超高分辨率圖片
├ layout 布局文件
├ menu 菜單
└ values 值,包括字符串,顏色等的定義
AndroidManifest.xml 這個文件是整個應用程序的主配置文件,所有組件都需要在這個文件中注冊。
proguard-project.txt 防止被別人反編譯,對代碼進行混淆。
project.properties 項目的屬性設置,比如SDK的版本。
用得最多的是src目錄和assets和res兩個資源目錄,以及AndroidManifest文件。
2.技術結構圖
1)Linux Kernel
Google選擇了Linux作為Android的底層支撐系統。當前的 Android系統是基于Linux2.6內核,其核心系統服務如安全性、內存管理、進程管理、網路協議以及驅動模型都依賴于Linux內核。
2)Android Runtime
運行時環境可分為核心庫和Dalvik虛擬機兩部分。
核心庫提供了Java語言API中的大多數功能,同時也包含了Android的一些核心API,如android.os、android.net、android.media等等。
Dalvik虛擬機是由Google公司自己設計專門用于Android平臺的Java虛擬機,它針對移動終端做了特殊的優化。
3)Libraries
系統庫是應用程序框架的支撐,是連接應用程序框架層與Linux內核層的重要紐帶。其主要包含以下幾個部分:
Surface Manager:執行多個應用程序時候,負責管理顯示與存取操作間的互動,另外也負責2D繪圖與3D繪圖進行顯示合成。
Media Framework:多媒體庫,支持多種常用的音頻、視頻格式錄制和回放,編碼格式包括MPEG4、MP3、H 264、AAC、ARM。
SQLite:輕量級的關系型數據庫引擎
OpenGL|ES:根據OpenGL ES 1.0 API標準實現的3D繪圖函數庫
FreeType:提供點陣字與向量字的描繪與顯示
WebKit:開源的瀏覽器引擎,支持CSS,JAVASCRIPT,DOM等腳本語言
SGL:底層的2D圖形渲染引擎
SSL:在Andorid上通信過程中實現安全認證
Libc:從BSD繼承來的標準C系統函數庫,專門為基于embedded linux的設備定制
4)Applications
應用程序框架層是開發者從事Android應用開發的基礎,很多核心應用程序也是通過這一層來實現其核心功能,該層簡化了組件的重用,開發人員可以直接使用它提供的組件進行快速的應用程序開發,也可以通過繼承而實現個性化的拓展。以下是這次層中,各個部分的功能:
Activity Manager(活動管理器):管理各個應用程序生命周期以及通常的導航回退功能。
Window Manager(窗口管理器):管理所有的窗口程序
Content Provider(內容提供器):通過它可以在不同應用程序之間存取或者分享數據
View System(視圖系統):構建應用程序的基本組件
Notification Manager(通知管理器):通過它應用程序可以在狀態欄中顯示自定義的提示信息
Package Manager(包管理器):Android系統內的程序管理,可以查看Android應用程序以及Activity的相關信息
Telephony Manager(電話管理器):管理所有的移動設備功能
Resource Manager(資源管理器):提供應用程序使用的各種非代碼資源,如本地化字符串、圖片、布局文件、顏色文件,主題樣式,二進制文件等
Location Manager(位置管理器):提供位置服務
XMPP Service(XMPP服務):提供Google Talk服務
3.基于組件的應用程序開發
把常見的功能封裝成一個個組件,根據需要的功能把相應的組件組合在一起,構成完整的應用程序,這就是基于組件進行應用程序開發的思想。
Android最重要的四種組件:
1)Activity
作為UI主要負責和用戶交互,接受用戶操作,把運行結果顯示給用戶。如果把一個Android程序比作一個網站的話,一個Activity就是一個網頁。但手機不宜有太多的Activity。
2)Service
主要負責完成耗時較長的工作,比如網絡連接和長時間的IO操作,沒有圖形化界面,在后臺默默運行。
3)Content Provider
內容提供者。可以看作是一種數據共享方法。它提供一個公開的地址,讓其他程序訪問我的數據。
4)BroadcastReceiver
廣播接收器。作用是監聽手機系統的行為。手機運行過程中,信息會向外發送廣播,比如手機沒電、藍牙關閉等。程序監聽到這些廣播可以作出相應的反應。
二、Android UI的重要概念
Android UI 的最重要的三個概念,Activity、View、Layout。
下面對這三個概念作一個初步的理解,先淺嘗輒止。這樣做的目的是先了解一下這些概念,從總體上對這些概念有一個把握和串通,方便后面的學習。
(一)Activity
1.Activity啟動流程
一個應用程序至少有一個Activity。且必須有一個默認的啟動Activity。
Android應用程序啟動的流程如下:
首先,Android操作系統會去訪問你的應用程序中的AndroidManifest.xml這個文件,決定啟動哪一個Activity。啟動默認的Activity之后,會生成這個Activity的對象,一般情況下是MainActivity。生成這個對象后,會去調用這個對象的onCreat方法。然后在onCreate方法里去讀取layout目錄下的activity_main.xml布局文件,來決定在應用程序里顯示什么內容。
2.Activity與布局文件
我們可以在布局文件里修改文字顯示的樣式,比如
android:textSize="80px" android:background="#FF0000"
所有在res里的文件都會在gen目錄里R.java這個文件里生成ID,布局文件也有它的ID。
public static final class layout { public static final int activity_main=0x7f030000; }
R.layout.activity_main就代表這個布局文件
然后在activity的onCreate函數中
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
setContentView就是顯示布局文件的內容。
3.在Activity中獲取代表控件的對象
為了滿足動態顯示的需要,寫死在布局文件里的控件顯然是不行的。
因此我們用代碼取代布局,如圖所示。這樣就可以動態的控制控件的樣式。
下面這行就是獲取代表控件的對象:
TextView textView = (TextView)findViewById(R.id.textView);
這涉及到View對象,下面就開始介紹View。
(二)View
1.什么是View
View就是控件。如下圖:
每一種控件都對應有一個類,View是所有控件的父類。
2.在Activity中獲取代表View的對象
首先,我們需要在layout文件里給控件加上一個唯一的ID:
android:id="@+id/textView"
然后,在Activity里聲明這個控件:
private TextView textView;
注:這里需要引用textView所在的包
import android.widget.TextView;
在Activity的函數里用findViewById獲取這個View,由于findViewById函數的返回類型是View,所以需要向下轉型為TextView:
注:這里不是生成對象,只是找到這個對象,對象的生成是由布局文件完成的。
textView = (TextView)findViewById(R.id.textView);
3.設置View的屬性
轉型完畢以后可以在Activity中對這個控件進行修改,控制它的屬性。例如:
textView.setText(“hello world”); textView.setBackgroundColor(Color.BLUE);
在布局里能做到的事情絕大部分代碼里也能做到。
4.為View設置監聽器
監聽器也是一種對象,它監控著控件對象狀態的變化。當控件遇到了某種事件,被點擊了,被滑動了等等,控件會通知監聽器,監聽器得到通知之后就執行一些操作。
控件與監聽器之間是綁定關系。
一個控件可以綁定多個監聽器,不同的監聽器用來響應不同的事件。比如監聽器一用來響應點擊事件,監聽器二用來響應長點擊事件……
我們以做一個計數器的應用為例,設計一個按鍵和一個文本框,每點擊一下按鈕,文本框里的數字加1。用這個例子來說明使用監聽器的步驟:
1)獲取代表控件的對象
首先,我們在布局文件里加一個Button和TextView,TextView初始值為0。
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40sp" android:background="#FF0000" android:text="0" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" />
再到Activity里引入包,聲明它
private Button button;
并獲取它
button = (Button)findViewById(R.id.button);
2)定義一個類,實現監聽器接口
我們在activity里定義一個監聽器,要使用一個內部類,并實現監聽器接口OnClickListener
class ButtonListener implements OnClickListener{ }
要注意的是,在導入包(CTRL+SHIFT+O)的時候,會彈出一個對話框讓你選擇引入哪個包,我們選擇View.OnClickListener。
Finish之后,我們要實現OnClickListener這個接口的抽象方法,在前面打叉的燈泡上點擊會彈出你需要的操作:
直接點擊Add unimplemented methods,Eclipse幫你完成抽象方法的復制,這個抽象方法就是onClick:
@Override public void onClick(View v) { // TODO Auto-generated method stub }
這個方法的作用是,當我們把ButtonListener監聽器綁定到Button控件上后,當Button被點擊時,會執行這個onClick方法。
聲明一個全局變量
int count=0;
接著我們完成onClick函數
@Override public void onClick(View v) { count++; textView.setText(count+""); }
至此,我們的監聽器就寫好了。
3)生成監聽器對象
在onCreate函數里生成監聽器對象:
ButtonListener buttonListener = new ButtonListener();
4)為控件綁定監聽器對象
然后綁定到button上
button.setOnClickListener(buttonListener);
完成。
在Android里監聽器種類非常多,而且不同控件監聽的方法也不一樣,但使用監聽器的流程永遠是這個流程。
(三)控件布局
1.什么是控件布局
所謂的控件布局方法,就是指控制控件在Activity當中的位置、大小、顏色以及其他控件樣式屬性的方法。
控件布局關系到不僅僅是好看的問題,更重要的是用戶的使用體驗。
可以在布局文件中完成布局,也可以在JAVA代碼中完成控件布局。
2.控件布局的分類
第一種布局方式是LAYOUT布局方式:
Linear Layout
線性布局,或者橫,或者豎,一個個的把控件按順序擺上去。
Relative Layout
相對布局,通過控件之間的相對位置決定控件的擺放方式。比如先擺好第一個控件,然后指定第二個控件擺放在第一個控件的下方,再指定第二個控件與第一個控件靠左對齊。有點類似DIV+CSS。
第二種布局方式是VIEW布局方式,主要是ADAPTER VIEW:
ListView
定義一個列表,每一項有自己的內容。這個布局是極其常用的布局。
Grid View
即網格布局,把屏幕分成幾等分的格子。
3.線性布局的基本使用方法
Eclipse默認生成項目的布局文件是Relative Layout。我們來嘗試下自己生成一個布局文件:
在layout文件夾上右鍵點new->Android XML file,彈出對話框如圖:
選擇根元素是LinearLayout,Finish。
生成代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > </LinearLayout>
android:layout_width="match_parent"表示寬度匹配父控件,也就是和activity寬度一樣。
android:orientation="vertical"表示方向垂直,因為LinearLayout還可以水平方向的排放控件,即將vertical改為horizontal
我們來加兩個控件:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FF0000" android:text="老大"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00FF00" android:text="老二"/>
android:layout_height="wrap_content"表示高度自適應內容。
然后把activity里設置為顯示我們自己寫的這個布局:
setContentView(R.layout.my_layout);
顯示結果如下:
如果我們現在什么都不改,只改LinearLayout的方向,由垂直改為水平,會出現什么情況呢?按理應該是在同一行顯示,但結果如下:
老二被老大擠跑了,這是因為我們第一個控件的寬度是指定的匹配父控件,把一行全占滿了,老二被擠出了屏幕,所以看不到了。
如果我們把老大的寬度改成wrap_content,也就是內容自適應,老二就出現了。
開發過程中,相對布局其實用得更多一些。這里是為了初步了解。
4.長度單位與內外邊距
1)距離單位之px
px即像素,如800*480的分辨率,是把屏幕分成橫向480個列,縱向800個行,第一個小格子就是一個像素。
但像素不是我們最好的選擇,原因下面解釋。
我們知道,市面上有各種各樣的手機,不同尺寸與不同分辨率都可能搭配在一臺手機上。如果我們用像素作單位,可以會出現下面這一種麻煩:
比如,我們設定了一個文本框,我們想讓它寬度占到屏幕寬度的一半,在一個320*480像素的手機上,寬度的一半自然是160px,于是我們給這個文本框寬度為160px。這個程序在320*480像素的手機上是正常的,但如果運行在一個640*960分辨率的手機上,就會在視覺上明顯變窄,如下圖所示:
這就是像素作為長度單位的缺陷。
怎么解決這個問題?我們必須用相對長度取代像素這種絕對長度。這個長度單位就是dp。
2)距離單位之dp
在解釋dp之前,必須要先解釋一個概念dpi。
前面解釋過像素實際上是指點的數量,而dpi(dots per inch),是指每英寸點的數量。
同樣尺寸的屏幕,分辨率可能會不同,也就是像素排列的密集程度不同。因此dpi表示的是屏幕的細膩程度。
如下圖:
在dpi的概念下,不同手機有了標準化的衡量指標。
由此,引申出一個新的長度單位dp。dp=dip(Device Independent pixels)
dp是一個相對的長度概念,它不代表實際長度,只代表實際長度,即像素基于dpi的系數。也就是說,不同dpi的手機屏幕上,1dp表示的像素長度是不同的。具體怎么不同,看dp換算成px的公式:
px=dp*(dpi/160)
1dp代表多少px呢?答案是不固定的,取決于手機的dpi是多少。
在dpi為160的屏幕上,也就是每英寸160像素的屏幕上,1dp代表1px。這是Android定義的基準值。
那么按照公式,一個20dp寬度的控件,在dpi160的屏幕上,顯示為20px。同樣的程序,換到dpi320的屏幕上運行,該控件的寬度就會顯示為40px。
3)距離單位之sp
sp沒有特殊的意思,它是為了適應手機用戶對系統字體大小的設置。
如果用戶將手機字體設為大,sp的值就會變大,反之亦然。
我們可以得出這樣一個推論:
在設置控件的高度和寬度時,一般用dp,而在設置字體大小的時候,一般用sp。
4)控件的外邊距與內邊距
如圖:
外邊距與內邊距之間就是控件的邊界。所以外邊距其實就是margin,內邊距其實就是padding。
內外邊距各有上、下、左、右四個屬性: