(1):Android的體系結構html
Application(應用程序) Application framework(應用程序框架) Libraries(庫) Android Runtime(運行時,包括核心庫和虛擬機) linux kernel(linux內核)linux
(2):Android的四大組件android
Activity service contentprovider(內容提供者) broadcastReceiver(廣播器)數據庫
(3): Android中四大組件的生命週期編程
(1)設置 android:configChanges="orientation" 和不設置這個屬性,這兩個效果是同樣的,activity都是從新創新安全
(2)橫屏切豎屏,以及豎屏切回橫屏,這兩個也是同樣的(以下總結),不會出現網上說的橫屏切回豎屏時,生命週期執行兩遍的問題服務器
1)從新建立activity的生命週期網絡
a)2.3上:onSaveInstanceState->onPause->onStop->onCreate->onStart->onRestoreInstanceState->onResume架構
b)4.0上(3.2我沒測試,只測試了4.0的):onPause->onSaveInstanceState->onStop->onCreate->onStart->onRestoreInstanceState->onResumeapp
2)不從新建立activity,只會調用 onConfigurationChanged
(3)targetSdkVersion會影響生命週期,targetSdkVersion在12及如下的話,設置了 android:configChanges="orientation|keyboardHidden" ,在機器上都不會從新建立activity,只會調用 onConfigurationChanged,若是設置targetSdkVersion>12的話,只在sdkVersion<=12的機器上有效果,>12的機器上activity仍是會從新建立(須要加上screenSize纔有效果)
(4)android2.3和android4.0的生命週期不同,2.3是先onSaveInstanceState,後onPause,4.0是先onPause,後onSaveInstanceState(這個我表示不想吐槽了)
a)建立ServerSocket的方法:
ServerSocket(Int localPort)
ServerSocket(int localport,int queueLimit)
ServerSocket(int localport,int queueLimit,InetAddress localAddr)
建立一個ServerSocket必須指定一個端口,以便客戶端可以向該端口號發送鏈接請求。端口的有效範圍是0-65535 (0-1023是系統預留的,最好大於1024)
0~1023的端口號爲系統所保留,例如http服務的端口號是80,telnet服務的端口號爲21,ftp爲23。因此咱們在選擇端口號時最好選擇大於1023的數,防止發生衝突。在建立Socket時,若是發生錯誤,將產生IOException,在程序中必須對其進行處理。因此在建立Socket或ServerSocket時必須捕獲或拋出異常。
b)ServerSocket操做
1,Socket accept()
accept()方法爲下一個傳入的鏈接請求建立Socket實例,並將已成功鏈接的Socket實例返回給服務器套接字,若是沒有鏈接請求,accept()方法將阻塞等待;
2,void close
close方法用於關閉套接字
2,Socket
a)建立Socket的方法:
Socket(InetAddress remoteAddress,int remotePort)
利用Socket構造函數,可建立一個TCP套接字後,先鏈接到指定的遠程地址和端口號。
Socket(InetAddress address,int port ,InetAddress localAddr ,int localPort)
Socket(InetAddress address, int port ,boolean stream)
Socket(SocketImpl impl)
address、host、port分別表示雙向鏈接中另外一方的IP地址、主機名、端口號
stream指明Socket是流Socket仍是數據報Socket
localAddr,bindAddr是本地機器的地址(ServerSocket的主機地址)
impl是Socket的父類,既能夠建立ServerSocket,也可建立Socket
b)操做Socket的方法
通訊過程當中順序:服務器端首先獲得輸入流,而後將輸入流信息輸出到其各個客戶端
Socket提供了getInputStream()和getOutputStream()方法來獲得輸入輸出流。而後再對輸入流輸出流進行讀寫操做,例如,對於服務器端,獲得Socket對象後,調用 getInputStream方法便可獲得來自客戶端的流,調用getOutStream方法可獲得向客戶端發送數據的流。對於客戶端,調用getInputStream方法便可獲得來自服務器的流,調用getOutStream方法可獲得向服務器端發送數據的流。
InputStream getInputStream()
OutputStream getOutputStream()
可調用Socket的close()方法進行關閉,在關閉前,應將與Socket相關的全部輸入輸出流關閉,正着打開,倒着關閉。
編程步驟:
建立服務器的步驟:
1, 指定端口實例化一個ServerSocket
2, 調用ServerSocket的accept方法以在等待鏈接期間形成阻塞
3, 獲取位於該底層Socket的流以進行讀寫操做
4, 將數據封裝成流
5, 對Socket進行讀寫
6, 關閉打開的流
建立客戶端的步驟:
1, 經過IP地址和端口實例化Socket,請求鏈接服務器
2, 獲取Socket上的流以進行讀寫
3, 把流包裝進BufferedReader/PrintWriter的實例
4, 對Socket進行讀寫
5, 關閉打開的流
當要監控多個客戶端時,可以使用類ExecutorService
其對象獲取方法:Executors.newCachedThreadPool();
調用該對象的execute(Runnable command)便可,在將來某個時間執行給定的命令。該命令可能在新的線程、已入池的線程或者正調用的線程中執行,這由 Executor 實現決定
三,使用基於UDP的Socket
a)建立DatagramSocket
DatagramSocket(byte [] data,int offset,int length,InetAddress remoteAddr,int remotePort)
該構造函數建立一個數據報文對象,數據包含在第一個參數data當中
Offset是指偏移量長度,length是指數據包長度。
b)建立DatagramSocket
DatagramSocket(int localPort)
以上構造函數將建立一個UDP套接字;
c)DatagramSocket:發送和接受
void send(DatagramPacket packet)
void receive(DatagramPacket packet)
send()方法用來發送DatagramPacket實例。一旦建立鏈接,數據報將發送到該套接字所鏈接的地址;
receive()方法將阻塞等待,知道接收到數據報文,並將報文中的數據複製到指定的DatagramPacket實例中。
補充:
對AndroidManifest.xml的配置必定不要忘了:
<uses-permission android:name="android.permission.INTERNET"/>
輸入和輸出流要用DataOutputStream和DataOutputStream,不能夠用PrintWriter、StreamReader等。
適用範圍:保存少許的數據,且這些數據的格式很是簡單:字符串型、基本類型的值。好比應用程序的各類配置信息(如是否打開音效、是否使用震動效果、小遊戲的玩家積分等),解鎖口 令密碼等
核心原理:保存基於XML文件存儲的key-value鍵值對數據,一般用來存儲一些簡單的配置信息。經過DDMS的File Explorer面板,展開文件瀏覽樹,很明顯SharedPreferences數據老是存儲在/data/data/<package name>/shared_prefs目錄下。SharedPreferences對象自己只能獲取數據而不支持存儲和修改,存儲修改是經過SharedPreferences.edit()獲取的內部接口Editor對象實現。 SharedPreferences自己是一 個接口,程序沒法直接建立SharedPreferences實例,只能經過Context提供的getSharedPreferences(String name, int mode)方法來獲取SharedPreferences實例,該方法中name表示要操做的xml文件名,第二個參數具體以下:
Context.MODE_PRIVATE: 指定該SharedPreferences數據只能被本應用程序讀、寫。
Context.MODE_WORLD_READABLE: 指定該SharedPreferences數據能被其餘應用程序讀,但不能寫。
Context.MODE_WORLD_WRITEABLE: 指定該SharedPreferences數據能被其餘應用程序讀,寫
Editor有以下主要重要方法:
SharedPreferences.Editor clear():清空SharedPreferences裏全部數據
SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key對應的數據,其中xxx 能夠是boolean,float,int等各類基本類型據
SharedPreferences.Editor remove(): 刪除SharedPreferences中指定key對應的數據項
boolean commit(): 當Editor編輯完成後,使用該方法提交修改
讀寫其餘應用的SharedPreferences: 步驟以下
一、在建立SharedPreferences時,指定MODE_WORLD_READABLE模式,代表該SharedPreferences數據能夠被其餘程序讀取
二、建立其餘應用程序對應的Context:
Context pvCount = createPackageContext("com.tony.app", Context.CONTEXT_IGNORE_SECURITY);這裏的com.tony.app就是其餘程序的包名
三、使用其餘程序的Context獲取對應的SharedPreferences
SharedPreferences read = pvCount.getSharedPreferences("lock", Context.MODE_WORLD_READABLE);
四、若是是寫入數據,使用Editor接口便可,全部其餘操做均和前面一致。
核心原理: Context提供了兩個方法來打開數據文件裏的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),這兩個方法第一個參數 用於指定文件名,第二個參數指定打開文件的模式。具體有如下值可選:
MODE_PRIVATE:爲默認操做模式,表明該文件是私有數據,只能被應用自己訪問,在該模式下,寫入的內容會覆蓋原文件的內容,若是想把新寫入的內容追加到原文件中。可 以使用Context.MODE_APPEND
MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內容,不然就建立新文件。
MODE_WORLD_READABLE:表示當前文件能夠被其餘應用讀取;
MODE_WORLD_WRITEABLE:表示當前文件能夠被其餘應用寫入。
除此以外,Context還提供了以下幾個重要的方法:
getDir(String name , int mode):在應用程序的數據文件夾下獲取或者建立name對應的子目錄
File getFilesDir():獲取該應用程序的數據文件夾得絕對路徑
String[] fileList():返回該應用數據文件夾的所有文件
讀寫sdcard上的文件
其中讀寫步驟按以下進行:
一、調用Environment的getExternalStorageState()方法判斷手機上是否插了sd卡,且應用程序具備讀寫SD卡的權限,以下代碼將返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
二、調用Environment.getExternalStorageDirectory()方法來獲取外部存儲器,也就是SD卡的目錄,或者使用"/mnt/sdcard/"目錄
三、使用IO流操做SD卡上的文件
注意點:手機應該已插入SD卡,對於模擬器而言,可經過mksdcard命令來建立虛擬存儲卡
必須在AndroidManifest.xml上配置讀寫SD卡的權限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SQLite是輕量級嵌入式數據庫引擎,它支持 SQL 語言,而且只利用不多的內存就有很好的性能。如今的主流移動設備像Android、iPhone等都使用SQLite做爲複雜數據的存儲引擎,在咱們爲移動設備開發應用程序時,也許就要使用到SQLite來存儲咱們大量的數據,因此咱們就須要掌握移動設備上的SQLite開發技巧
Android系統中能實現全部應用程序共享的一種數據存儲方式,因爲數據一般在各應用間的是互相私密的,因此此存儲方式較少使用,可是其又是必不可少的一種存儲方式。例如音頻,視頻,圖片和通信錄,通常均可以採用此種方式進行存儲。每一個Content Provider都會對外提供一個公共的URI(包裝成Uri對象),若是應用程序有數據須要共享時,就須要使用Content Provider爲這些數據定義一個URI,而後其餘的應用程序就經過Content Provider傳入這個URI來對數據進行操做。
在Android的UI開發中,咱們常常會使用Handler來控制主UI程序的界面變化。有關Handler的做用,咱們總結爲:與其餘線程協同工做,接收其餘線程的消息並經過接收到的消息更新主UI線程的內容。
咱們假設在一個UI界面上面,有一個按鈕,當點擊這個按鈕的時候,會進行網絡鏈接,並把網絡上的一個字符串拿下來顯示到界面上的一個 TextView上面,這時就出現了一個問題,若是這個網絡鏈接的延遲過大,多是10秒鐘甚至更長,那咱們的界面將處於一直假死狀態,而若是這段時間超 過5秒鐘的話,程序會出現異常。
這時咱們會想到使用線程來完成以上工做,即當按鈕被按下的時候新開啓一個線程來完成網絡鏈接工做,並把獲得的結果更新到UI上面。可是,這時候又會 出現另外一個問題,在Android中,主線程是非線程安全的,也就是說UI的更新只能在本線程中完成,其餘線程沒法直接對主線程進行操做。
爲了解決以上問題,Android設計了Handler機制,由Handler來負責與子線程進行通信,從而讓子線程與主線程之間創建起協做的橋樑,使Android的UI更新的問題獲得完美的解決。
Handler的工做原理
通常狀況下,在主線程中咱們綁定了Handler,並在事件觸發上面建立新的線程用於完成某些耗時的操做,當子線程中的工做完成以後,會對Handler發送一個完成的信號,而Handler接收到信號後,就進行主UI界面的更新操做。
andriod提供了 Handler 和 Looper 來知足線程間的通訊。
Handler 先進先出原則。
Looper類用來管理特定線程內對象之間的消息交換(Message Exchang搜索e)。
1)Looper: 一個線程能夠產生一個Looper對象,由它來管理此線程裏的Message Queue(消息隊列)。
2)Handler: 你能夠構造Handler對象來與Looper溝通,以便push新消息到Message Queue裏;或者接收Looper從Message Queue取出)所送來的消息。
3) Message Queue(消息隊列):用來存放線程放入的消息。
4)線程:UI thread 一般就是main thread,而Android啓動程序時會替它創建一個Message Queue。
Android程序啓動後會起一個進程,全部的組件都在這個進程裏面運行。開始這個進程只包含一個線程(備註進程怎麼能包含線程,我認爲說法有誤),叫作UI主線程,負責處理UI界面的顯示更新。對於一些費時的操做(超過5S會卡頓)須要單獨啓動一個子線程去處理。子線程處理完畢將結果通知給UI主線程,主線程獲得結果後更新UI界面。子線程與UI主線程的通訊在android中使用了消息機制來完成,那麼是怎麼完成的呢?這就和handler 機制的原理,簡而言之言而總之,就是須要兩樣樣古老的東西,消息隊列、輪詢。也就是說,主線程起來之後有一個消息隊列,同時和該隊列配對的有一個輪詢,而子線程有這個消息隊列的引用,那這樣,子線程處理完之後就會向主線程的消息隊列發消息,主線程輪詢本身的隊列,發現有未處理的消息就進行處理。
在電腦術語中,統一資源標識符(Uniform Resource Identifier,或URI)是一個用於標識某一互聯網資源名稱的字符串。 該種標識容許用戶對任何(包括本地和互聯網)的資源經過特定的協議進行交互操做。URI由包括肯定語法和相關協議的方案所定義。