1. 請描述下Activity的生命周期。2. 如果背景的Activity由于某原因被系統回收了,如何在被系統回收之前儲存目前狀态?3. 如何将一個Activity設定成視窗的樣式。(Edited by Sodino)4. 如何退出Activity?如何安全退出已調用多個Activity的Application?5. 請介紹下Android中常用的五種布局。6. 請介紹下Android的資料存儲方式。(Edited by Sodino)7. 請介紹下ContentProvider是如何實作資料共享的。(Edited by Sodino)8. 如何啟用Service,如何停用Service。(Edited by Sodino)9. 注冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意。10. 請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關系。11. AIDL的全稱是什麼?如何工作?能處理哪些類型的資料?12. 請解釋下Android程式運作時權限與檔案系統權限的差別。(Edited by Sodino)13. 系統上安裝了多種浏覽器,能否指定某浏覽器通路指定頁面?請說明原由。14. 有一個一維整型數組int[]data儲存的是一張寬為width,高為height的圖檔像素值資訊。請寫一個算法,将該圖檔所有的白色不透明(0xffffffff)像素點的透明度調整為50%。15. 你如何評價Android系統?優缺點。 1. 請描述下Activity的生命周期 http://weizhulin.blog.51cto.com/1556324/311495 詳細介紹一下這幾個方法中系統在做什麼以及我們應該做什麼: onCreate: 在這裡建立界面 ,做一些資料的初始化工作 onStart: 到這一步變成使用者可見不可互動 的 onResume: 變成和使用者可互動 的,(在activity棧系統通過棧的方式管理這些個 Activity的最上面,運作完彈出棧,則回到上一個Activity) onPause: 到這一步是可見但不可互動 的,系統會停止動畫 等消耗CPU 的事情 從上文的描述已經知道,應該在這裡儲存你的一些資料,因為這個時候 你的程式的優先級降低,有可能被系統收回。在這裡儲存的資料,應該在 onResume裡讀出來,注意:這個方法裡做的事情時間要短,因為下一 個activity不會等到這個方法完成才啟動 onstop: 變得不可見 ,被下一個activity覆寫了 onDestroy:這是activity被幹掉前最後一個被調用方法了,可能是外面類調用finish方 法或者是系統為了節省空間将它暫時性的幹掉,可以用isFinishing()來判 斷它,如果你有一個Progress Dialog線上程中轉動,請在onDestroy裡 把他cancel掉,不然等線程結束的時候,調用Dialog的cancel方法會抛 異常的。 onPause,onstop, onDestroy,三種狀态 下 activity都有可能被系統幹掉 為了保證程式的正确性,你要在onPause()裡寫上持久層操作的代碼,将使用者編輯的内容都儲存到存儲媒體上(一般都是資料庫)。實際工作中因為生命周期的變化而帶來的問題也很多,比如你的應用程式起了新的線程在跑,這時候中斷了,你還要去維護那個線程,是暫停還是殺掉還是資料復原,是吧?因為Activity可能被殺掉,是以線程中使用的變量和一些界面元素就千萬要注意了,一般我都是采用Android的消息機制[Handler,Message]來處理多線程和界面互動的問題。這個我後面會講一些,最近因為這些東西頭已經很大了,等我理清思緒再跟大家分享。 2. 如果背景的Activity由于某原因被系統回收了,如何在被系統回收之前儲存目前狀态? 當你的程式中某一個Activity A 在運作時中,主動或被動地運作另一個新的Activity B 這個時候A會執行Java代碼
B 完成以後又會來找A, 這個時候就有兩種情況,一種是A被回收,一種是沒有被回收,被回 收的A就要重新調用onCreate()方法,不同于直接啟動的是這回onCreate()裡是帶上參數 savedInstanceState,沒被收回的就還是onResume就好了。 savedInstanceState是一個Bundle對象,你基本上可以把他了解為系統幫你維護的一個Map對象。在onCreate()裡你可能會用到它,如果正常啟動onCreate就不會有它,是以用的時候要判斷一下是否為空。 Java代碼 if(savedInstanceState !=null){ long id =savedInstanceState.getLong("id"); } if(savedInstanceState !=null){ long id = savedInstanceState.getLong("id");} 就像官方的Notepad教程裡的情況,你正在編輯某一個note,突然被中斷,那麼就把這個note的id記住,再起來的時候就可以根據這個id去把那個note取出來,程式就完整一些。這也是看你的應用需不需要儲存什麼,比如你的界面就是讀取一個清單,那就不需要特殊記住什麼,哦,沒準你需要記住滾動條的位置... 3. 如何将一個Activity設定成視窗的樣式簡單你隻需要設定 一下Activity的主題就可以了在AndroidManifest.xml 中定義 Activity的 地方一句話: Xml代碼
就變成半透明的,[友情提示-.-]類似的這種activity的屬性可以在android.R.styleable類的AndroidManifestActivity方法中看到,AndroidManifest.xml中所有元素的屬性的介紹都可以參考這個類android.R.styleable 上面說的是屬性名稱,具體有什麼值是在android.R.style中可以看到,比如這個"@android:style/Theme.Dialog"就對應于android.R.style.Theme_Dialog ,('_'換成'.'<--注意:這個是文章内容不是笑臉)就可以用在描述檔案中了,找找類定義和描述檔案中的對應關系就都明白了。 4. 如何退出Activity 對于單一Activity的應用來說,退出很簡單,直接finish()即可。 當然,也可以用killProcess()和System.exit()這樣的方法。 現提供幾個方法,供參考: 1、抛異常強制退出: 該方法通過抛異常,使程式Force Close。 驗證可以,但是,需要解決的問題是,如何使程式結束掉,而不彈出Force Close的視窗。 2、記錄打開的Activity: 每打開一個Activity,就記錄下來。在需要退出時,關閉每一個Activity即可。 3、發送特定廣播: 在需要結束應用時,發送一個特定的廣播,每個Activity收到廣播後,關閉即可。 4、遞歸退出 在打開新的Activity時使用startActivityForResult,然後自己加标志,在onActivityResult中處理,遞歸關閉。 除了第一個,都是想辦法把每一個Activity都結束掉,間接達到目的。 但是這樣做同樣不完美。 你會發現,如果自己的應用程式對每一個Activity都設定了nosensor,在兩個Activity結束的間隙,sensor可能有效了。 但至少,我們的目的達到了,而且沒有影響使用者使用。 為了程式設計友善,最好定義一個Activity基類,處理這些共通問題。 5.請介紹下Android中常用的五種布局 Android布局是應用界面開發的重要一環,在Android中,共有五種布局方式,分别是:FrameLayout(架構布局),LinearLayout (線性布局),AbsoluteLayout(絕對布局),RelativeLayout(相對布局),TableLayout(表格布局)。 一、FrameLayout 這個布局可以看成是牆腳堆東西,有一個四方的矩形的左上角牆腳,我們放了第一個東西,要再放一個,那就在放在原來放的位置的上面,這樣依次的放,會蓋住原來的東西。這個布局比較簡單,也隻能放一點比較簡單的東西。 二、LinearLayout 線性布局,這個東西,從外框上可以了解為一個div,他首先是一個一個從上往下羅列在螢幕上。每一個LinearLayout裡面又可分為垂直布局(android:orientation="vertical")和水準布局(android:orientation="horizontal" )。當垂直布局時,每一行就隻有一個元素,多個元素依次垂直往下;水準布局時,隻有一行,每一個元素依次向右排列。 linearLayout中有一個重要的屬性 android:layout_weight="1",這個weight在垂直布局時,代表行距;水準的時候代表列寬;weight值越大就越大。 三、AbsoluteLayout 絕對布局猶如div指定了absolute屬性,用X,Y坐标來指定元素的位置android:layout_x="20px" android:layout_y="12px" 這種布局方式也比較簡單,但是在垂直随便切換時,往往會出問題,而且多個元素的時候,計算比較麻煩。 四、RelativeLayout 相對布局可以了解為某一個元素為參照物,來定位的布局方式。主要屬性有: 相對于某一個元素 android:layout_below="@id/aaa" 該元素在 id為aaa的下面 android:layout_toLeftOf="@id/bbb" 改元素的左邊是bbb 相對于父元素的地方 android:layout_alignParentLeft="true" 在父元素左對齊 android:layout_alignParentRight="true" 在父元素右對齊 還可以指定邊距等,具體詳見API 五。TableLayout 表格布局類似Html裡面的Table。每一個TableLayout裡面有表格行TableRow,TableRow裡面可以具體定義每一個元素,設定他的對齊方式 android:gravity="" 。 每一個布局都有自己适合的方式,另外,這五個布局元素可以互相嵌套應用,做出美觀的界面。 6. 請介紹下Android的資料存儲方式 Android提供了5種方式存儲資料: --使用SharedPreferences存儲資料; --檔案存儲資料; --SQLite資料庫存儲資料; --使用ContentProvider存儲資料; --網絡存儲資料;[url=]先 說下,Preference,File,DataBase這三種方式分别對應的目錄是/data/data/Package Name/Shared_Pref,/data/data/Package Name/files, /data/data/Package Name/database。[/url]在Android中通常使用File存儲方式是用Context.openFileOutput(StringfileName, int mode)和Context.openFileInput(String fileName)。 Context.openFileOutput(String fileName, intmode)生成的檔案自動存儲在/data/data/PackageName/files目錄下,其全路徑是/data/data/Package Name/files/fileName。注意下,這裡的參數fileName不可以包含路徑分割符(如"/")。 通常來說,這種方式生成的檔案隻能在這個apk内通路。但這個結論是指使用Context.openFileInput(StringfileName)的方式。使用這種方式,每個apk隻可以通路自己的/data/data/PackageName/files目錄下的檔案,原因很簡單,參數fileName中不可以包含路徑分割符,Android會自動在/data/data/PackageName/files目錄下尋找檔案名為fileName的檔案。一:使用SharedPreferences存儲資料 首先說明SharedPreferences存儲方式,它是Android提供的用來存儲一些簡單配置資訊的一種機制,例如:登入使用者的使用者名與密碼。其采用了Map資料結構來存儲資料,以鍵值的方式存儲,可以簡單的讀取與寫入,具體執行個體如下: void ReadSharedPreferences(){ String strName,strPassword; SharedPreferences user =getSharedPreferences(“user_info”,0); strName = user.getString(“NAME”,””); strPassword = user getString(“PASSWORD”,””); } void WriteSharedPreferences(String strName,StringstrPassword){ uer.edit(); user.putString(“NAME”, strName); user.putString(“PASSWORD” ,strPassword); user.commit(); 資料讀取與寫入的方法都非常簡單,隻是在寫入的時候有些差別:先調用edit()使其處于編輯狀态,然後才能修改資料,最後使用commit()送出修改的資料。實際上SharedPreferences是采用了XML格式将資料存儲到裝置中,在DDMS中的FileExplorer中的/data/data/<packagename>/shares_prefs下。以上面的資料存儲結果為例,打開後可以看到一個user_info.xml的檔案,打開後可以看到: <?xml version=”1.0″encoding=”UTF-8″?> <map> <stringname=”NAME”>moandroid</string> <string name=”PASSWORD”>SharedPreferences</string> </map> 使用SharedPreferences是有些限制的:隻能在同一個包内使用,不能在不同的包之間使用。二:檔案存儲資料 檔案存儲方式是一種較常用的方法,在Android中讀取/寫入檔案的方法,與Java中實作I/O的程式是完全一樣的,提供了openFileInput()和openFileOutput()方法來讀取裝置上的檔案。FilterInputStream, FilterOutputStream等可以到Java iopackage說明中去詳細學習,不再此詳細說明,具體執行個體如下: String fn = “moandroid.log”; FileInputStream fis = openFileInput(fn); FileOutputStream fos =openFileOutput(fn,Context.MODE_PRIVATE); 除此之外,Android還提供了其他函數來操作檔案,詳細說明請閱讀Android SDK。 三:網絡存儲資料 網絡存儲方式,需要與Android網絡資料包打交道,關于Android 網絡資料包的詳細說明,請閱讀Android SDK引用了JavaSDK的哪些package?。四:ContentProvider 1、ContentProvider簡介 當應用繼承ContentProvider類,并重寫該類用于提供資料和存儲資料的方法,就可以向其他應用共享其資料。雖然使用其他方法也可以對外共享資料,但資料通路方式會因資料存儲的方式而不同,如:采用檔案方式對外共享資料,需要進行檔案操作讀寫資料;采用sharedpreferences共享資料,需要使用sharedpreferencesAPI讀寫資料。而使用ContentProvider共享資料的好處是統一了資料通路方式。? 2、Uri類簡介 Uri代表了要操作的資料,Uri主要包含了兩部分資訊:1.需要操作的ContentProvider,2.對ContentProvider中的什麼資料進行操作,一個Uri由以下幾部分組成: 1.scheme:ContentProvider(内容提供者)的scheme已經由Android所規定為:content://。 2.主機名(或Authority):用于唯一辨別這個ContentProvider,外部調用者可以根據這個辨別來找到它。 3.路徑(path):可以用來表示我們要操作的資料,路徑的建構應根據業務而定,如下: ? 要操作contact表中id為10的記錄,可以建構這樣的路徑:/contact/10 ? 要操作contact表中id為10的記錄的name字段, contact/10/name ? 要操作contact表中的所有記錄,可以建構這樣的路徑:/contact? 要操作的資料不一定來自資料庫,也可以是檔案等他存儲方式,如下: 要操作xml檔案中contact節點下的name節點,可以建構這樣的路徑:/contact/name 如果要把一個字元串轉換成Uri,可以使用Uri類中的parse()方法,如下: Uri uri =Uri.parse("content://com.changcheng.provider.contactprovider/contact") 3、UriMatcher、ContentUrist和ContentResolver簡介 因為Uri代表了要操作的資料,是以我們很經常需要解析Uri,并從Uri中擷取資料。Android系統提供了兩個用于操作Uri的工具類,分别為UriMatcher和ContentUris 。掌握它們的使用,會便于我們的開發工作。 ? UriMatcher:用于比對Uri,它的用法如下: 1.首先把你需要比對Uri路徑全部給注冊上,如下: //常量UriMatcher.NO_MATCH表示不比對任何路徑的傳回碼(-1)。 UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法比對content://com.changcheng.sqlite.provider.contactprovider/contact路徑,傳回比對碼為1 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact”, 1);//添加需要比對uri,如果比對就會傳回比對碼 //如果match()方法比對content://com.changcheng.sqlite.provider.contactprovider/contact/230路徑,傳回比對碼為2 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact/#”, 2);//#号為通配符 2.注冊完需要比對的Uri後,就可以使用uriMatcher.match(uri)方法對輸入的Uri進行比對,如果比對就傳回比對碼,比對碼是調用addURI()方法傳入的第三個參數,假設比對content://com.changcheng.sqlite.provider.contactprovider/contact路徑,傳回的比對碼為1。 ? ContentUris:用于擷取Uri路徑後面的ID部分,它有兩個比較實用的方法: ? withAppendedId(uri, id)用于為路徑加上ID部分 ? parseId(uri)方法用于從路徑中擷取ID部分 ? ContentResolver:當外部應用需要對ContentProvider中的資料進行添加、删除、修改和查詢操作時,可以使用ContentResolver 類來完成,要擷取ContentResolver對象,可以使用Activity提供的getContentResolver()方法。ContentResolver使用insert、delete、update、query方法,來操作資料。五:總結說明 以上5中存儲方式,在以後的開發過程中,根據設計目标、性能需求、空間需求等找到合适的資料存儲方式。Android中的資料存儲都是私有的,其他應用程式都是無法通路的,除非通過ContentResolver擷取其他程式共享的資料。采用檔案方式對外共享資料,需要進行檔案操作讀寫資料;采用sharedpreferences共享資料,需要使用sharedpreferencesAPI讀寫資料。而使用ContentProvider共享資料的好處是統一了資料通路方式。8.如何啟用Service, |