編輯:關於Android編程
雖然做Android開發已經有一段時間了,但是很少寫博客一類的東西。今天算是第一次真正意義上在CSDN平台上發表自己的一些看法,心裡既有欣喜,也有一些壓力。欣喜在於,能將自己的想法公之與眾,並且能夠和大家一起交流技術上的東西。壓力在於,自己要能夠將一些較高質量的作品奉獻給大家。閒話先說到這,來談談我對Android開發的一些理解吧。
Android中的多層架構極具拓展性。裡面也包含很多的機制,例如Bind機制,Handler機制等等。但是我們最熟悉的應該就是Android的四大組件了,Activity,Broadcast Receiver,Service,Content Provider.而這四大組件又通過Intent這一個紐帶去傳遞數據,進行連接的。這其中的一些機制,究竟是怎樣實現的呢,又運用了什麼樣的設計模式呢,這是我們需要探究的問題。當然要清楚地知道其中的原理,需要有一定的功力,也即要有一定的理論基礎,才能明白其中的一些巧妙之處。
要想深入得理解Android的設計理論知識。首先得知道怎樣去使用Android的四大組件。讓我們簡單的看一下吧。
最最重要的一大組件就是Activity了。
我們可以看到Activity的7個生命周期以及相互之間的轉換關系。十分明確一個Activity處於生命周期的哪個部分,才能夠幫助我們更好地利用生命周期,在不同的時間段去干不同的事情。例如一些特殊情況,譬如按下Home鍵時,當前的Activity會被掛到任務棧的後台,Activity會執行onPause()和onStop()方法。當用戶重新點開這個APP時,會執行onRestart()方法,然後執行onStart()方法,onResume()方法,直至運行狀態。當Activity處於後台時,除非系統內存不足,否則是不會殺死這個Activity所在的進程的。還有當手機屏幕進行切屏時,Activity會被銷毀並且重新創建;整個生命周期會從這是一定要注意將系統的狀態保存。。。等等一系列的問題。
另外一個重要的事情是,Activity為我們提供了4種啟動模式,幫助我們去設置不同的Activity狀態,當然這4種啟動模式都是基於對Activity回退棧(Back Stack)的處理。四種啟動模式分別是Standard,SingleTop,SingleTask,SingleInstance。這四種啟動模式相信大家都知道,但是應該在什麼時候,選擇哪種模式呢。這裡給出我的一些理解給大家參考。
Standard:是個富二代,去超市裡,看到什麼玩具就要什麼玩具,不管家裡有沒有,而長輩都會一直給他買的。而且Google API中默認大伙都是富二代
SingleTop:家裡有點錢,孩子剛剛買過的玩具,就不會再買了,孩子要的時候,直接拿給他用。但是如果孩子的玩具已經玩舊,父母會立馬給孩子買新的。
SingleTask:家裡條件一般般。小孩要玩玩具的時候,只要家裡有,就不會買新的,哪怕玩具放在箱子的最裡面,父母也會把玩具上面的東西全部扔掉,直至拿到玩具。(這是絕對地溺愛啊)
SingleInstance:家裡最貧窮的,但是自由。小孩也是任性的,想要什麼玩具,就讓父母造,父母也是很細心,造好的玩具都一一存放好(不放在一起)。孩子要玩,只要有,就能很快拿給他,沒有的話,就再造一個。(感覺和富二代是兩種完全不同的生活)
當然,以上都是戲說這個回退棧的,僅供大家參考。官方的描述是這樣的:
"standard"(默認模式)
默認。系統在啟動 Activity 的任務中創建 Activity 的新實例並向其傳送 Intent。Activity 可以多次實例化,而每個實例均可屬於不同的任務,並且一個任務可以擁有多個實例。
"singleTop"
如果當前任務的頂部已存在 Activity 的一個實例,則系統會通過調用該實例的onNewIntent()方法向其傳送 Intent,而不是創建 Activity 的新實例。Activity 可以多次實例化,而每個實例均可屬於不同的任務,並且一個任務可以擁有多個實例(但前提是位於返回棧頂部的 Activity 並不是 Activity 的現有實例)。
例如,假設任務的返回棧包含根 Activity A 以及 Activity B、C 和位於頂部的 D(堆棧是 A-B-C-D;D 位於頂部)。收到針對 D 類 Activity 的 Intent。如果 D 具有默認的"standard"啟動模式,則會啟動該類的新實例,且堆棧會變成 A-B-C-D-D。但是,如果 D 的啟動模式是"singleTop",則 D 的現有實例會通過onNewIntent()接收 Intent,因為它位於堆棧的頂部;而堆棧仍為 A-B-C-D。但是,如果收到針對 A 類 Activity 的 Intent,則會向堆棧添加 B 的新實例,即便其啟動模式為"singleTop"也是如此。
注:為某個 Activity 創建新實例時,用戶可以按“返回”按鈕返回到前一個 Activity。但是,當 Activity 的現有實例處理新 Intent 時,則在新 Intent 到達onNewIntent()之前,用戶無法按“返回”按鈕返回到 Activity 的狀態。
"singleTask"
系統創建新任務並實例化位於新任務底部的 Activity。但是,如果該 Activity 的一個實例已存在於一個單獨的任務中,則系統會通過調用現有實例的onNewIntent()方法向其傳送 Intent,而不是創建新實例。一次只能存在 Activity 的一個實例。
注:盡管 Activity 在新任務中啟動,但是用戶按“返回”按鈕仍會返回到前一個 Activity。
"singleInstance"。
與"singleTask"相同,只是系統不會將任何其他 Activity 啟動到包含實例的任務中。該 Activity 始終是其任務唯一僅有的成員;由此 Activity 啟動的任何 Activity 均在單獨的任務中打開。大家可以查看官方文檔https://developer.android.com/guide/components/tasks-and-back-stack.html。Activity就介紹到這了。
2.Service
Service也是一個很重要的組件。在Service中可以進行一些耗時操作以及與界面無關的操作。有人可能會問了,耗時操作放在工作線程裡不就可以了嗎,為什麼要使用Service呢?我的理解是這樣的:Service進行了很好的封裝,除了進行耗時操作以及與界面無關的事情外,還能很好的受控制。例如我們調用context.startService之後,可以方便的調用stopSelf或者stopService。並且可以通過設置Service的粘性決定是否重新啟動以及怎樣啟動這個Service繼續工作,而這一點是普通的線程做不到的。當然Service還有另外一種開啟方式,即綁定Service。綁定Service相比startService更具有靈活性,而且封裝得很好。開啟Service和綁定Service是調用不同的生命周期的。
可以看出startService是調用的onCreate() ------>onStartCommand()------>onDestroy(),而bindService調用的是onCreate()------>onBind()------>onUnbind()
startService要執行的onStartCommand()方法的返回值是int類型的,即三種常量
START_STICKY(常量值:1):sticky的意思是“粘性的”。使用這個返回值時,我們啟動的服務跟應用程序"粘"在一起,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務。當再次啟動服務時,傳入的第一個參數將為null;
START_NOT_STICKY(常量值:2):“非粘性的”。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統不會自動重啟該服務。
START_REDELIVER_INTENT(常量值:3):重傳Intent。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
以上三種情況,可以理解為發生車禍後的人:
START_STICKY:(常量值:1)車禍後自己蘇醒,但是失憶;
START_NOT_STICKY:(常量值:2)車禍後再也沒有蘇醒;
START_REDELIVER_INTENT:(常量值:3)車禍後自己蘇醒,依然保持記憶。
除此之外,Service可與AIDL結合實現IPC,這裡先不做介紹
3.Broadcast Receiver
廣播接收器。廣播接收器可以實現跨Activity的通信。可以自定義Broadcast Receiver來傳遞數據,也能通過Broadcast Receiver接收系統的廣播。當然廣播也有不同的形式,如有序廣播和無序廣播。甚至接收廣播後對其攔截,對信息進行修改,然後將數據發送出去。這裡不做細致的討論。具體可參見國內目前最全面的介紹——Android中的BroadCastReceiver文章,寫得還是比較全面的。
4.Content Provider
內容提供者。內容提供者可以安全的將私有數據庫中的數據有選擇性暴露給外界,方便外界的訪問。通過設置特定的Uri來向外界提供訪問數據的入口。具體是設置匹配規則,然後進行匹配。自定義內容提供者,需要實現創建,獲得類型及增刪改查等六個方法。通過獲得系統的內容提供者,則可以通過query獲得系統數據庫中的數據。Android API中是這樣描述的:
內容提供程序管理對結構化數據集的訪問。它們封裝數據,並提供用於定義數據安全性的機制。 內容提供程序是連接一個進程中的數據與另一個進程中運行的代碼的標准界面。
如果您想要訪問內容提供程序中的數據,可以將應用的Context中的ContentResolver對象用作客戶端來與提供程序通信。ContentResolver對象會與提供程序對象(即實現ContentProvider的類實例)通信。 提供程序對象從客戶端接收數據請求,執行請求的操作並返回結果。
如果您不打算與其他應用共享數據,則無需開發自己的提供程序。 不過,您需要通過自己的提供程序在您自己的應用中提供自定義搜索建議。 如果您想將復雜的數據或文件從您的應用復制並粘貼到其他應用中,也需要創建您自己的提供程序。
Android 本身包括的內容提供程序可管理音頻、視頻、圖像和個人聯系信息等數據。android.provider軟件包參考文檔中列出了部分提供程序。 任何 Android 應用都可以訪問這些提供程序,但會受到某些限制。
具體Content Provider的用法可以參見API文檔之Content Provider
以上簡單地聊完了四大組件,當然這些組件的應用只是皮毛。但是也需要多使用,並且不斷總結,才能收獲不一樣的東西。
二、不斷磨練,不斷學習
任何的學習的過程都是要付出一定代價的,Android的知識比較多,而且每個模塊也是比較深刻的。對於初學者來說,最忌諱的是急躁。我剛學習Android時就是比較急躁的,總想著很快把學完,但是後來發現這是很困難的。要想弄清楚怎麼回事,必須靜下心來,慢慢琢磨。只有真正懂了,才知道怎樣去造輪子,只有會造輪子了,你的車才能很好的跑起來。
好了,今天就寫到這裡了,在Android方面我還要學習很多,希望一點一點進步
前幾篇文章,我也是費勁心思寫了一個ListView系列的三部曲,雖然在內容上可以說是絕對的精華,但是很多朋友都表示看不懂。好吧,這個系列不僅是把大家給難倒了,
一、Service的種類1.按運行地點分類: 類別 區別 優點 缺點 應用 本地服務 (Local) 該服務依附在主進程上 服務依附在主進程上而不是獨立
做過電商類應用的朋友可能都會遇到一個比較頭疼的問題:復雜的首頁布局如何實現。參考百度糯米,美團,bilibili等應用,都會發現其首頁的布局相對復雜,例如下圖bilibi
首先聲明本文是基於GitHub上baoyongzhang的SwipeMenuListView修改而來,該項目地址:https://github.com/baoyongzh
Android應用程序窗口的繪圖表面在創建完成之後,我們就可以從上到下地