1 如何導(dǎo)入外部數(shù)據(jù)庫(kù)
把原數(shù)據(jù)庫(kù)包括在項(xiàng)目源碼的 res/raw
android系統(tǒng)下數(shù)據(jù)庫(kù)應(yīng)該存放在 /data/data/com..(package name)/ 目錄下,所以我們需要做的是把已有的數(shù)據(jù)庫(kù)傳入那個(gè)目錄下.操作方法是用FileInputStream讀取原數(shù)據(jù)庫(kù),再用FileOutputStream把讀取到的東西寫(xiě)入到那個(gè)目錄.
2 本地廣播和全局廣播有什么差別
因廣播數(shù)據(jù)在本應(yīng)用范圍內(nèi)傳播,不用擔(dān)心隱私數(shù)據(jù)泄露的問(wèn)題。 不用擔(dān)心別的應(yīng)用偽造廣播,造成安全隱患。 相比在系統(tǒng)內(nèi)發(fā)送全局廣播,它更高效。
3 LaunchMode應(yīng)用場(chǎng)景
standard,創(chuàng)建一個(gè)新的Activity。
singleTop,棧頂不是該類型的Activity,創(chuàng)建一個(gè)新的Activity。否則,onNewIntent。
singleTask,回退棧中沒(méi)有該類型的Activity,創(chuàng)建Activity,否則,onNewIntent+ClearTop。
singleInstance,回退棧中,只有這一個(gè)Activity,沒(méi)有其他Activity。
singleTop適合接收通知啟動(dòng)的內(nèi)容顯示頁(yè)面。
例如,某個(gè)新聞客戶端的新聞內(nèi)容頁(yè)面,如果收到10個(gè)新聞推送,每次都打開(kāi)一個(gè)新聞內(nèi)容頁(yè)面是很煩人的。
singleTask適合作為程序入口點(diǎn)。
例如瀏覽器的主界面。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器,只會(huì)啟動(dòng)主界面一次,其余情況都會(huì)走onNewIntent,并且會(huì)清空主界面上面的其他頁(yè)面。
singleInstance應(yīng)用場(chǎng)景:
鬧鈴的響鈴界面。 你以前設(shè)置了一個(gè)鬧鈴:上午6點(diǎn)。在上午5點(diǎn)58分,你啟動(dòng)了鬧鈴設(shè)置界面,并按 Home 鍵回桌面;在上午5點(diǎn)59分時(shí),你在微信和朋友聊天;在6點(diǎn)時(shí),鬧鈴響了,并且彈出了一個(gè)對(duì)話框形式的 Activity(名為 AlarmAlertActivity) 提示你到6點(diǎn)了(這個(gè) Activity 就是以 SingleInstance 加載模式打開(kāi)的),你按返回鍵,回到的是微信的聊天界面,這是因?yàn)?AlarmAlertActivity 所在的 Task 的棧只有他一個(gè)元素, 因此退出之后這個(gè) Task 的??樟?。如果是以 SingleTask 打開(kāi) AlarmAlertActivity,那么當(dāng)鬧鈴響了的時(shí)候,按返回鍵應(yīng)該進(jìn)入鬧鈴設(shè)置界面。
4 Android事件傳遞流程:
事件都是從Activity.dispatchTouchEvent()開(kāi)始傳遞
事件由父View傳遞給子View,ViewGroup可以通過(guò)onInterceptTouchEvent()方法對(duì)事件攔截,停止其向子view傳遞
如果事件從上往下傳遞過(guò)程中一直沒(méi)有被停止,且最底層子View沒(méi)有消費(fèi)事件,事件會(huì)反向往上傳遞,這時(shí)父View(ViewGroup)可以進(jìn)行消費(fèi),如果還是沒(méi)有被消費(fèi)的話,最后會(huì)到Activity的onTouchEvent()函數(shù)。
如果View沒(méi)有對(duì)ACTION_DOWN進(jìn)行消費(fèi),之后的其他事件不會(huì)傳遞過(guò)來(lái),也就是說(shuō)ACTION_DOWN必須返回true,之后的事件才會(huì)傳遞進(jìn)來(lái)
OnTouchListener優(yōu)先于onTouchEvent()對(duì)事件進(jìn)行消費(fèi)
5 ANR對(duì)話框
應(yīng)用在5秒內(nèi)未響應(yīng)用戶的輸入事件(如按鍵或者觸摸)
BroadcastReceiver未在10秒內(nèi)完成相關(guān)的處理
Service在特定的時(shí)間內(nèi)無(wú)法處理完成 20秒
可以使用一下方法
使用AsyncTask處理耗時(shí)IO操作。
使用Thread或者HandlerThread時(shí),調(diào)用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設(shè)置優(yōu)先級(jí),否則仍然會(huì)降低程序響應(yīng),因?yàn)槟J(rèn)Thread的優(yōu)先級(jí)和主線程相同。
使用Handler處理工作線程結(jié)果,而不是使用Thread.wait()或者Thread.sleep()來(lái)阻塞主線程。
Activity的onCreate和onResume回調(diào)中盡量避免耗時(shí)的代碼
BroadcastReceiver中onReceive代碼也要盡量減少耗時(shí),建議使用IntentService處理
6 Requestlayout,onlayout,onDraw,DrawChild
requestLayout()方法 :會(huì)導(dǎo)致調(diào)用measure()過(guò)程 和 layout()過(guò)程 。 將會(huì)根據(jù)標(biāo)志位判斷是否需要ondraw
onLayout()方法(如果該View是ViewGroup對(duì)象,需要實(shí)現(xiàn)該方法,對(duì)每個(gè)子視圖進(jìn)行布局)
調(diào)用onDraw()方法繪制視圖本身 (每個(gè)View都需要重載該方法,ViewGroup不需要實(shí)現(xiàn)該方法)
drawChild()去重新回調(diào)每個(gè)子視圖的draw()方法
7 Handler
1 當(dāng)Android程序第一次創(chuàng)建的時(shí)候,在主線程同時(shí)會(huì)創(chuàng)建一個(gè)Looper對(duì)象。Looper實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的消息隊(duì)列,一個(gè)接著一個(gè)處理Message對(duì)象。程序框架所有主要的事件(例如:屏幕上的點(diǎn)擊時(shí)間,Activity生命周期的方法等等)都包含在Message對(duì)象中,然后添加到Looper的消息隊(duì)列中,一個(gè)一個(gè)處理。主線程的Looper存在整個(gè)應(yīng)用程序的生命周期內(nèi)。
2 當(dāng)一個(gè)Handler對(duì)象在主線程中創(chuàng)建的時(shí)候,它會(huì)關(guān)聯(lián)到Looper的 message queue 。Message添加到消息隊(duì)列中的時(shí)候Message會(huì)持有當(dāng)前Handler引用,當(dāng)Looper處理到當(dāng)前消息的時(shí)候,會(huì)調(diào)用Handler#handleMessage(Message).
3 在java中,no-static的內(nèi)部類會(huì) 隱式的 持有當(dāng)前類的一個(gè)引用。static的類則沒(méi)有。
8 onSaveInstanceState,onRestoreInstanceState
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法,它們并不一定會(huì)被觸發(fā)。當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足、用戶直接按Home鍵)由系統(tǒng)銷毀一個(gè)Activity,onSaveInstanceState() 會(huì)被調(diào)用。但是當(dāng)用戶主動(dòng)去銷毀一個(gè)Activity時(shí),例如在應(yīng)用中按返回鍵,onSaveInstanceState()就不會(huì)被調(diào)用。除非該activity是被用戶主動(dòng)銷毀的,通常onSaveInstanceState()只適合用于保存一些臨時(shí)性的狀態(tài),而onPause()適合用于數(shù)據(jù)的持久化保存。
9 OOM
Out Of Merrory,Android系統(tǒng)的每一個(gè)應(yīng)用程序都設(shè)置一個(gè)硬性的Dalvik Heap Size最大限制閾值,如果申請(qǐng)的內(nèi)存資源超過(guò)這個(gè)限制,系統(tǒng)就會(huì)拋出OOM錯(cuò)誤
內(nèi)存泄漏,阻止對(duì)象回收:
類的靜態(tài)變量持有大數(shù)據(jù)對(duì)象
非靜態(tài)內(nèi)部類存在靜態(tài)實(shí)例
資源對(duì)象未關(guān)閉
Handler內(nèi)存泄漏
解決方法:
使用更加輕量的數(shù)據(jù)結(jié)構(gòu) 例如,我們可以考慮使用ArrayMap/SparseArray而不是HashMap等傳統(tǒng)數(shù)據(jù)結(jié)構(gòu)
避免在Android里面使用Enum
減小Bitmap對(duì)象的內(nèi)存占用,Bitmap對(duì)象的復(fù)用
使用更小的圖片
StringBuilder 在有些時(shí)候,代碼中會(huì)需要使用到大量的字符串拼接的操作,這種時(shí)候有必要考慮使用StringBuilder來(lái)替代頻繁的“+”。
避免在onDraw方法里面執(zhí)行對(duì)象的創(chuàng)建
10 Asynctask
內(nèi)存泄露: 非靜態(tài)內(nèi)部類AsynTask會(huì)隱式地持有外部類的引用,如果其生命周期大于外部activity的生命周期,就會(huì)出現(xiàn)內(nèi)存泄漏
注意要復(fù)寫(xiě)AsynTask的onCancel方法,把里面的socket,file等,該關(guān)掉的要及時(shí)關(guān)掉
在 Activity 的onDestory()方法中調(diào)用Asyntask.cancal方法
Asyntask內(nèi)部使用弱引用的方式來(lái)持有Activity
若Activity已經(jīng)銷毀,此時(shí)AsynTask執(zhí)行完并且返回結(jié)果,會(huì)報(bào)異常嗎?
當(dāng)一個(gè)App旋轉(zhuǎn)時(shí),整個(gè)Activity會(huì)被銷毀和重建。當(dāng)Activity重啟時(shí),AsyncTask中對(duì)該Activity的引用是無(wú)效的,因此onPostExecute()就不會(huì)起作用,若AsynTask正在執(zhí)行,折會(huì)報(bào) view not attached to window manager 異常
同樣也是生命周期的問(wèn)題,在 Activity 的onDestory()方法中調(diào)用Asyntask.cancal方法,讓二者的生命周期同步