1 如何導入外部數(shù)據(jù)庫:
把原數(shù)據(jù)庫包括在項目源碼的 res/raw
android系統(tǒng)下數(shù)據(jù)庫應該存放在 /data/data/com..(package name)/ 目錄下嵌巷,所以我們需要做的是把已有的數(shù)據(jù)庫傳入那個目錄下.操作方法是用FileInputStream讀取原數(shù)據(jù)庫论寨,再用FileOutputStream把讀取到的東西寫入到那個目錄.
2 本地廣播和全局廣播有什么差別:
因廣播數(shù)據(jù)在本應用范圍內(nèi)傳播兽叮,不用擔心隱私數(shù)據(jù)泄露的問題。 不用擔心別的應用偽造廣播寒矿,造成安全隱患。 相比在系統(tǒng)內(nèi)發(fā)送全局廣播若债,它更高效符相。
3 intentService作用是什么,AIDL解決了什么問題:
生成一個默認的且與主線程互相獨立的工作者線程來執(zhí)行所有傳送至onStartCommand() 方法的Intetnt。
生成一個工作隊列來傳送Intent對象給你的onHandleIntent()方法蠢琳,同一時刻只傳送一個Intent對象啊终,這樣一來,你就不必擔心多線程的問題傲须。在所有的請求(Intent)都被執(zhí)行完以后會自動停止服務蓝牲,所以,你不需要自己去調(diào)用stopSelf()方法來停止泰讽。
該服務提供了一個onBind()方法的默認實現(xiàn)例衍,它返回null
提供了一個onStartCommand()方法的默認實現(xiàn),它將Intent先傳送至工作隊列已卸,然后從工作隊列中每次取出一個傳送至onHandleIntent()方法佛玄,在該方法中對Intent對相應的處理。
AIDL (Android Interface Definition Language) 是一種IDL 語言累澡,用于生成可以在Android設(shè)備上兩個進程之間進行進程間通信(interprocess communication, IPC)的代碼梦抢。如果在一個進程中(例如Activity)要調(diào)用另一個進程中(例如Service)對象的操作,就可以使用AIDL生成可序列化的參數(shù)愧哟。 AIDL IPC機制是面向接口的奥吩,像COM或Corba一樣哼蛆,但是更加輕量級。它是使用代理類在客戶端和實現(xiàn)端傳遞數(shù)據(jù)圈驼。
4 Activity/Window/View三者的差別,fragment的特點:
Activity像一個工匠(控制單元)人芽,Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀绩脆,Xml配置像窗花圖紙萤厅。
1 在Activity中調(diào)用attach,創(chuàng)建了一個Window
2 創(chuàng)建的window是其子類PhoneWindow靴迫,在attach中創(chuàng)建PhoneWindow
3 在Activity中調(diào)用setContentView(R.layout.xxx)
4 其中實際上是調(diào)用的getWindow().setContentView()
5 調(diào)用PhoneWindow中的setContentView方法
6 創(chuàng)建ParentView:作為ViewGroup的子類惕味,實際是創(chuàng)建的DecorView(作為FramLayout的子類)
7 將指定的R.layout.xxx進行填充通過布局填充器進行填充【其中的parent指的就是DecorView】
8 調(diào)用到ViewGroup
9 調(diào)用ViewGroup的removeAllView(),先將所有的view移除掉
10 添加新的view:addView()
fragment 特點:
? ? Fragment可以作為Activity界面的一部分組成出現(xiàn)玉锌;
? ? 可以在一個Activity中同時出現(xiàn)多個Fragment名挥,并且一個Fragment也可以在多個Activity中使用;
? ? 在Activity運行過程中主守,可以添加禀倔、移除或者替換Fragment;
? ? Fragment可以響應自己的輸入事件参淫,并且有自己的生命周期救湖,它們的生命周期會受宿主Activity的生命周期影響。
5 描述一次網(wǎng)絡請求的流程:
6 Handler,Thread和HandlerThread的差別:
http://blog.csdn.net/guolin_blog/article/details/9991569
http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/
從Android中Thread(java.lang.Thread -> java.lang.Object)描述可以看出涎才,Android的Thread沒有對Java的Thread做任何封裝鞋既,但是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread做了很多便利Android系統(tǒng)的封裝耍铜。
android.os.Handler可以通過Looper對象實例化邑闺,并運行于另外的線程中,Android提供了讓Handler運行于其它線程的線程實現(xiàn)棕兼,也是就HandlerThread陡舅。HandlerThread對象start后可以獲得其Looper對象,并且使用這個Looper對象實例Handler程储。
7 低版本SDK實現(xiàn)高版本api:
自己實現(xiàn)或@TargetApi annotation
8 LaunchMode應用場景:
standard蹭沛,創(chuàng)建一個新的Activity。
singleTop章鲤,棧頂不是該類型的Activity摊灭,創(chuàng)建一個新的Activity。否則败徊,onNewIntent帚呼。
singleTask,回退棧中沒有該類型的Activity,創(chuàng)建Activity煤杀,否則眷蜈,onNewIntent+ClearTop。
注意:
? ? 1 設(shè)置了"singleTask"啟動模式的Activity沈自,它在啟動的時候酌儒,會先在系統(tǒng)中查找屬性值affinity等于它的屬性值taskAffinity的Task存在; 如果存在? ? ? ? ?這樣的Task枯途,它就會在這個Task中啟動忌怎,否則就會在新的任務棧中啟動。因此酪夷, 如果我們想要設(shè)置了"singleTask"啟動模式的Activity在新? ? ? ? ? ? ? 任務中啟動榴啸,就要為它設(shè)置一個獨立的taskAffinity屬性值。
? ? ?2 如果設(shè)置了"singleTask"啟動模式的Activity不是在新的任務中啟動時晚岭,它會在已有的任務中查看是否已經(jīng)存在相應的Activity實例鸥印, 如果存? ? ? ? ? ? ?在,就會把位于這個Activity實例上面的Activity全部結(jié)束掉坦报,即最終這個Activity 實例會位于任務的Stack頂端中库说。
? ? ?3 在一個任務棧中只有一個”singleTask”啟動模式的Activity存在。他的上面可以有其他的Activity片择。這點與singleInstance是有區(qū)別的璃弄。
singleInstance,回退棧中构回,只有這一個Activity,沒有其他Activity疏咐。
singleTop適合接收通知啟動的內(nèi)容顯示頁面纤掸。
例如,某個新聞客戶端的新聞內(nèi)容頁面浑塞,如果收到10個新聞推送借跪,每次都打開一個新聞內(nèi)容頁面是很煩人的。
singleTask適合作為程序入口點酌壕。
例如瀏覽器的主界面掏愁。不管從多少個應用啟動瀏覽器,只會啟動主界面一次卵牍,其余情況都會走onNewIntent果港,并且會清空主界面上面的其他頁面。
singleInstance應用場景:
鬧鈴的響鈴界面糊昙。 你以前設(shè)置了一個鬧鈴:上午6點辛掠。在上午5點58分,你啟動了鬧鈴設(shè)置界面,并按 Home 鍵回桌面萝衩;在上午5點59分時回挽,你在微信和朋友聊天;在6點時猩谊,鬧鈴響了千劈,并且彈出了一個對話框形式的 Activity(名為 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵牌捷,回到的是微信的聊天界面墙牌,這是因為 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 因此退出之后這個 Task 的椧搜欤空了憔古。如果是以 SingleTask 打開 AlarmAlertActivity,那么當鬧鈴響了的時候淋袖,按返回鍵應該進入鬧鈴設(shè)置界面鸿市。
9? 什么情況導致內(nèi)存泄漏:
1.資源對象沒關(guān)閉造成的內(nèi)存泄漏
描述: 資源性對象比如(Cursor,F(xiàn)ile文件等)往往都用了一些緩沖即碗,我們在不使用的時候焰情,應該及時關(guān)閉它們,以便它們的緩沖及時回收內(nèi)存剥懒。它們的緩沖不僅存在于 java虛擬機內(nèi)内舟,還存在于java虛擬機外。如果我們僅僅是把它的引用設(shè)置為null,而不關(guān)閉它們初橘,往往會造成內(nèi)存泄漏验游。因為有些資源性對象,比如 SQLiteCursor(在析構(gòu)函數(shù)finalize(),如果我們沒有關(guān)閉它保檐,它自己會調(diào)close()關(guān)閉)耕蝉,如果我們沒有關(guān)閉它,系統(tǒng)在回收它時也會關(guān)閉它夜只,但是這樣的效率太低了垒在。因此對于資源性對象在不使用的時候,應該調(diào)用它的close()函數(shù)扔亥,將其關(guān)閉掉场躯,然后才置為null.在我們的程序退出時一定要確保我們的資源性對象已經(jīng)關(guān)閉。 程序中經(jīng)常會進行查詢數(shù)據(jù)庫的操作旅挤,但是經(jīng)常會有使用完畢Cursor后沒有關(guān)閉的情況踢关。如果我們的查詢結(jié)果集比較小,對內(nèi)存的消耗不容易被發(fā)現(xiàn)粘茄,只有在常時間大量操作的情況下才會復現(xiàn)內(nèi)存問題耘成,這樣就會給以后的測試和問題排查帶來困難和風險。
2.構(gòu)造Adapter時,沒有使用緩存的convertView
描述: 以構(gòu)造ListView的BaseAdapter為例瘪菌,在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 來向ListView提供每一個item所需要的view對象撒会。初始時ListView會從BaseAdapter中根據(jù)當前的屏幕布局實例化一定數(shù)量的 view對象,同時ListView會將這些view對象緩存起來师妙。當向上滾動ListView時诵肛,原先位于最上面的list item的view對象會被回收,然后被用來構(gòu)造新出現(xiàn)的最下面的list item默穴。這個構(gòu)造過程就是由getView()方法完成的怔檩,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。由此可以看出蓄诽,如果我們不去使用 convertView薛训,而是每次都在getView()中重新實例化一個View對象的話,即浪費資源也浪費時間仑氛,也會使得內(nèi)存占用越來越大乙埃。 ListView回收list item的view對象的過程可以查看: android.widget.AbsListView.java --> voidaddScrapView(View scrap) 方法。 示例代碼:
public?View?getView(int?position,?ViewconvertView,?ViewGroup?parent)?{
View?view?=?new?Xxx(...);
...?...
return?view;
}
修正示例代碼:
public?View?getView(int?position,?ViewconvertView,?ViewGroup?parent)?{
View?view?=?null;
if?(convertView?!=?null)?{
view?=?convertView;
populate(view,?getItem(position));
...
}?else?{
view?=?new?Xxx(...);
...
}
return?view;
}
3.Bitmap對象不在使用時調(diào)用recycle()釋放內(nèi)存
描述: 有時我們會手工的操作Bitmap對象锯岖,如果一個Bitmap對象比較占內(nèi)存介袜,當它不在被使用的時候,可以調(diào)用Bitmap.recycle()方法回收此對象的像素所占用的內(nèi)存出吹,但這不是必須的遇伞,視情況而定〈防危可以看一下代碼中的注釋:
/**? ?Free?up?the?memory?associated?with?thisbitmap's?pixels,?and?mark?the? ?bitmap?as?"dead",?meaning?itwill?throw?an?exception?if?getPixels()?or? ?setPixels()?is?called,?and?will?drawnothing.?This?operation?cannot?be? ?reversed,?so?it?should?only?be?called?ifyou?are?sure?there?are?no? ?further?uses?for?the?bitmap.?This?is?anadvanced?call,?and?normally?need? ?not?be?called,?since?the?normal?GCprocess?will?free?up?this?memory?when? ?there?are?no?more?references?to?thisbitmap.? */
4.試著使用關(guān)于application的context來替代和activity相關(guān)的context
這是一個很隱晦的內(nèi)存泄漏的情況鸠珠。有一種簡單的方法來避免context相關(guān)的內(nèi)存泄漏。最顯著地一個是避免context逃出他自己的范圍之外秋麸。使用Application context跳芳。這個context的生存周期和你的應用的生存周期一樣長,而不是取決于activity的生存周期竹勉。如果你想保持一個長期生存的對象,并且這個對象需要一個context,記得使用application對象娄琉。你可以通過調(diào)用 Context.getApplicationContext() or Activity.getApplication()來獲得次乓。更多的請看這篇文章如何避免 Android內(nèi)存泄漏。
5.注冊沒取消造成的內(nèi)存泄漏
一些Android程序可能引用我們的Anroid程序的對象(比如注冊機制)孽水。即使我們的Android程序已經(jīng)結(jié)束了票腰,但是別的引用程序仍然還有對我們的Android程序的某個對象的引用,泄漏的內(nèi)存依然不能被垃圾回收女气。調(diào)用registerReceiver后未調(diào)用unregisterReceiver杏慰。 比如:假設(shè)我們希望在鎖屏界面(LockScreen)中,監(jiān)聽系統(tǒng)中的電話服務以獲取一些信息(如信號強度等),則可以在LockScreen中定義一個 PhoneStateListener的對象缘滥,同時將它注冊到TelephonyManager服務中轰胁。對于LockScreen對象,當需要顯示鎖屏界面的時候就會創(chuàng)建一個LockScreen對象朝扼,而當鎖屏界面消失的時候LockScreen對象就會被釋放掉赃阀。 但是如果在釋放 LockScreen對象的時候忘記取消我們之前注冊的PhoneStateListener對象,則會導致LockScreen無法被垃圾回收擎颖。如果不斷的使鎖屏界面顯示和消失榛斯,則最終會由于大量的LockScreen對象沒有辦法被回收而引起OutOfMemory,使得system_process 進程掛掉。 雖然有些系統(tǒng)程序搂捧,它本身好像是可以自動取消注冊的(當然不及時)驮俗,但是我們還是應該在我們的程序中明確的取消注冊,程序結(jié)束時應該把所有的注冊都取消掉允跑。
6.集合中對象沒清理造成的內(nèi)存泄漏
我們通常把一些對象的引用加入到了集合中王凑,當我們不需要該對象時,并沒有把它的引用從集合中清理掉吮蛹,這樣這個集合就會越來越大荤崇。如果這個集合是static的話,那情況就更嚴重了潮针。
10? ANR定位和修正:
主線程被IO操作(從4.0之后網(wǎng)絡IO不允許在主線程中)阻塞术荤。
主線程中存在耗時的計算
主線程中錯誤的操作,比如Thread.wait或者Thread.sleep等 Android系統(tǒng)會監(jiān)控程序的響應狀況每篷,一旦出現(xiàn)下面兩種情況瓣戚,則彈出ANR對話框
應用在5秒內(nèi)未響應用戶的輸入事件(如按鍵或者觸摸)
BroadcastReceiver未在10秒內(nèi)完成相關(guān)的處理
Service在特定的時間內(nèi)無法處理完成 20秒
使用AsyncTask處理耗時IO操作。
使用Thread或者HandlerThread時焦读,調(diào)用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設(shè)置優(yōu)先級子库,否則仍然會降低程序響應,因為默認Thread的優(yōu)先級和主線程相同矗晃。
使用Handler處理工作線程結(jié)果仑嗅,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。
Activity的onCreate和onResume回調(diào)中盡量避免耗時的代碼
BroadcastReceiver中onReceive代碼也要盡量減少耗時张症,建議使用IntentService處理仓技。