仍是屏幕旋轉這個例子,在重建Activity的時候,會回調 Activity.onRetainNonConfigurationInstance()
從新傳遞一個新的對象給AsyncTask,完成引用的更新html
考慮到線程安全問題java
當一個App旋轉時,整個Activity會被銷燬和重建。當Activity重啓時,AsyncTask中對該Activity的引用是無效的,所以onPostExecute()就不會起做用,若AsynTask正在執行,折會報 view not attached to window manager 異常mysql
一樣也是生命週期的問題,在 Activity 的onDestory()方法中調用Asyntask.cancal方法,讓兩者的生命週期同步linux
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並非生命週期方法,不一樣於 onCreate()、onPause()等生命週期方法,它們並不必定會被觸發。當應用遇到意外狀況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity,onSaveInstanceState() 會被調用。可是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。除非該activity是被用戶主動銷燬的,一般onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。android
咱們能夠在AndroidManifest.xml配置的android:launchMode屬性爲以上四種之一。
1. standard standard模式是默認的啓動模式,不用爲配置android:launchMode屬性便可,固然也能夠指定值爲standard。standard啓動模式,無論有沒有已存在的實例,都生成新的實例。
2. singleTop 咱們在上面的基礎上爲指定屬性android:launchMode=」singleTop」,系統就會按照singleTop啓動模式處理跳轉行爲。跳轉時系統會先在棧結構中尋找是否有一個Activity實例正位於棧頂,若是有則再也不生成新的,而是直接使用。若是系統發現存在有Activity實例,但不是位於棧頂,從新生成一個實例。 這就是singleTop啓動模式,若是發現有對應的Activity實例正位於棧頂,則重複利用,再也不生成新的實例。
3. singleTask 若是發現有對應的Activity實例,則使此Activity實例之上的其餘Activity實例通通出棧,使此Activity實例成爲棧頂對象,顯示到幕前。
4. singleInstance 這種啓動模式比較特殊,由於它會啓用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證再也不有其餘Activity實例進入。git
Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。github
棧通常以包名命名,兩個應用的簽名和udid要相同web
Fragment能夠做爲Activity界面的一部分組成出現.一個Activity中能夠同時出現多個Fragment,並一個Fragment也能夠在多個Activity中使用.算法
在Activity中能夠添加,刪除,替換Fragment.Fragment能夠響應本身的輸入時間,而且有本身的生命週期,但其生命週期收Activity影響.sql
* @param from\>=0&&from\<=1.0f * @param to\>=0&&to\<=1.0f * * */ private void dimBackground(final float from, final float to) { final Window window = getWindow(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to); valueAnimator.setDuration(500); valueAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { WindowManager.LayoutParams params = window.getAttributes(); params.alpha = (Float) animation.getAnimatedValue(); window.setAttributes(params); } }); valueAnimator.start(); }
本地廣播在本應用範圍內傳播,不用擔憂隱私數據泄露,不用擔憂別的應用僞造廣播.相比全局廣播,本地廣播更高效.
1.靜態註冊:在清單文件中註冊, 常見的有監聽設備啓動,常駐註冊不會隨程序生命週期改變
2.動態註冊:在代碼中註冊,隨着程序的結束,也就中止接受廣播了
補充一點:有些廣播只能經過動態方式註冊,好比時間變化事件、屏幕亮滅事件、電量變動事件,由於這些事件觸發頻率一般很高,若是容許後臺監聽,會致使進程頻繁建立和銷燬,從而影響系統總體性能
a:從MVC的角度考慮(應用程序內) 其實回答這個問題的時候還能夠這樣問,android爲何要有那4大組件,如今的移動開發模型基本上也是照搬的web那一套MVC架構,只不過是改了點嫁妝而已。android的四大組件本質上就是爲了實現移動或者說嵌入式設備上的MVC架構,它們之間有時候是一種相互依存的關係,有時候又是一種補充關係,引入廣播機制能夠方便幾大組件的信息和數據交互。
b:程序間互通消息(例如在本身的應用程序內監聽系統來電)
c:效率上(參考UDP的廣播協議在局域網的方便性)
d:設計模式上(反轉控制的一種應用,相似監聽者模式)
具體參見:[http://blog.csdn.net/t12x3456/article/details/9256609]
IntentService是Service的子類,是一個異步的,會自動中止的服務,很好解決了傳統的Service中處理完耗時操做忘記中止並銷燬Service的問題
生成一個默認的且與線程相互獨立的工做線程執行全部發送到onStartCommand()方法的Intent,能夠在onHandleIntent()中處理.
串行隊列,每次只運行一個任務,不存在線程安全問題,全部任務執行完後自動中止服務,不須要本身手動調用stopSelf()來中止.
UI線程
在AndroidManifest.xml文件中對於intent-filter能夠經過android:priority = 「1000」這個屬性設置最高優先級,1000是最高值,若是數字越小則優先級越低,同時適用於廣播。
當一個應用程序須要把本身的數據暴露給其餘程序使用時,該就用程序就可經過提供ContentProvider來實現;其餘應用程序就可經過ContentResolver來操做ContentProvider暴露的數據。 一旦某個應用程序經過ContentProvider暴露了本身的數據操做接口,那麼無論該應用程序是否啓動,其餘應用程序均可以經過該接口來操做該應用程序的內部數據,包括增長數據、刪除數據、修改數據、查詢數據等。
ContentProvider以某種Uri的形式對外提供數據,容許其餘應用訪問或修改數據;其餘應用程序使用ContentResolver根據Uri去訪問操做指定數據。 步驟:
1. 定義本身的ContentProvider類,該類須要繼承Android提供的ContentProvider基類。
2. 在AndroidManifest.xml文件中註冊個ContentProvider,註冊ContenProvider時須要爲它綁定一個URL。 例: android:authorities=」com.myit.providers.MyProvider」 /> 說明:authorities就至關於爲該ContentProvider指定URL。 註冊後,其餘應用程序就能夠經過該Uri來訪問MyProvider所暴露的數據了。
3. 接下來,使用ContentResolver操做數據,Context提供了以下方法來獲取ContentResolver對象。 通常來講,ContentProvider是單例模式,當多個應用程序經過ContentResolver來操做 ContentProvider提供的數據時,ContentResolver調用的數據操做將會委託給同一個ContentProvider處理。 使用ContentResolver操做數據只需兩步: 一、調用Activity的ContentResolver獲取ContentResolver對象。 二、根據須要調用ContentResolver的insert()、delete()、update()和query()方法操做數據便可
ContentProvider的主要仍是用於數據共享,其能夠對Sqlite,SharePreferences,File等進行數據操做用來共享數據。而sql的能夠理解爲數據庫的一門語言,可使用它完成CRUD等一系列的操做
文件存儲: 經過Java.io.FileInputStream和java.io.FileOutputStream這兩個類來實現對文件的讀寫,java.io.File類則用來構造一個具體指向某個文件或者文件夾的對象。
SharedPreferences: SharedPreferences是一種輕量級的數據存儲機制,他將一些簡單的數據類型的數據,包括boolean類型,int類型,float類型,long類型以及String類型的數據,以鍵值對的形式存儲在應用程序的私有Preferences目錄(/data/data/<包名>/shared_prefs/)中,這種Preferences機制普遍應用於存儲應用程序中的配置信息。
SQLite數據庫: 當應用程序須要處理的數據量比較大時,爲了更加合理地存儲、管理、查詢數據,咱們每每使用關係數據庫來存儲數據。Android系統的不少用戶數據,如聯繫人信息,通話記錄,短信息等,都是存儲在SQLite數據庫當中的,因此利用操做SQLite數據庫的API能夠一樣方便的訪問和修改這些數據。
ContentProvider: 主要用於在不一樣的應用程序之間實現數據共享的功能,不一樣於sharepreference和文件存儲中的兩種全局可讀寫操做模式,內容提供其能夠選擇只對哪一部分數據進行共享,從而保證咱們程序中的隱私數據不會有泄漏的風險
在Android中不能直接打開res aw目錄中的數據庫文件,而須要在程序第一次啓動時將該文件複製到手機內存或SD卡的某個目錄中,而後再打開該數據庫文件。複製的基本方法是使用getResources().openRawResource方法得到res aw目錄中資源的 InputStream對象,而後將該InputStream對象中的數據寫入其餘的目錄中相應文件中。在Android SDK中可使用SQLiteDatabase.openOrCreateDatabase方法來打開任意目錄中的SQLite數據庫文件。
中文70(包括標點),英文160,160個字節。
Application的Context是一個全局靜態變量,SDK的說明是隻有當你引用這個context的生命週期超過了當前activity的生命週期,而和整個應用的生命週期掛鉤時,纔去使用這個application的context。
在android中context能夠做不少操做,可是最主要的功能是加載和訪問資源。在android中有兩種context,一種是 application context,一種是activity context,一般咱們在各類類和方法間傳遞的是activity context。
「aar」包是 Android 的類庫項目的二進制發行包。
文件擴展名是.aar,maven 項目類型應該也是aar,但文件自己是帶有如下各項的 zip 文件:
/AndroidManifest.xml (mandatory)
/classes.jar (mandatory)
/res/ (mandatory)
/R.txt (mandatory)
/assets/ (optional)
/libs/*.jar (optional)
/jni//*.so (optional)
/proguard.txt (optional)
/lint.jar (optional)
這些條目是直接位於 zip 文件根目錄的。 其中R.txt 文件是aapt帶參數–output-text-symbols的輸出結果。
jar打包不能包含資源文件,好比一些drawable文件、xml資源文件之類的,aar能夠。
SQLite做爲輕量級的數據庫,比MySQL還小,但支持SQL語句查詢,提升性能能夠考慮經過原始通過優化的SQL查詢語句方式處理
參考:[http://www.cnblogs.com/devinzhang/archive/2012/01/16/2323949.html]
能夠將dictionary.db文件複製到Eclipse Android工程中的res aw目錄中。全部在res aw目錄中的文件不會被壓縮,這樣能夠直接提取該目錄中的文件。能夠將dictionary.db文件複製到res aw目錄中
[http://jiajixin.cn/2014/09/16/webview-js-safety/]
Service設置成START_STICKY kill 後會被重啓(等待5秒左右),重傳Intent,保持與重啓前同樣
經過 startForeground將進程設置爲前臺進程, 作前臺服務,優先級和前臺應用一個級別,除非在系統內存很是缺,不然此進程不會被 kill
雙進程Service: 讓2個進程互相保護**,其中一個Service被清理後,另外沒被清理的進程能夠當即重啓進程
QQ黑科技: 在應用退到後臺後,另起一個只有 1 像素的頁面停留在桌面上,讓本身保持前臺狀態,保護本身不被後臺清理工具殺死
在已經root的設備下,修改相應的權限文件,將App假裝成系統級的應用 Android4.0系列的一個漏洞,已經確承認行
用C編寫守護進程(即子進程) : Android系統中當前進程(Process)fork出來的子進程,被系統認爲是兩個不一樣的進程。當父進程被殺死的時候,子進程仍然能夠存活,並不受影響。鑑於目前提到的在Android->- Service層作雙守護都會失敗,咱們能夠fork出c進程,多進程守護。死循環在那檢查是否還存在,具體的思路以下(Android5.0以上的版本不可行)
在NDK環境中將1中編寫的C代碼編譯打包成可執行文件(BUILD_EXECUTABLE)。主進程啓動時將守護進程放入私有目錄下,賦予可執行權限,啓動它便可。
聯繫廠商,加入白名單
參考:[http://blog.csdn.net/qinjuning/article/details/7310620]
widget和Notification中
1 首先嚐試讀取IMEI、Mac地址、CPU號等物理信息(有很多工具能夠修改IMEI);
2 若是均失敗,能夠本身生成UUID而後保存到文件(文件也可能被篡改或刪除)
參考:[http://blog.csdn.net/xushuaic/article/details/25077179]
驗證碼應該只有兩種獲取方式: 從服務器端獲取圖片, 經過短信服務,將驗證碼發送給客戶端這兩種
Map裏實現了Serializable接口,而在Bundle實現了Parcelable的接口
Bundle 父類 BaseBundle內部確實有個 ArrayMap
DOM,SAX,Pull解析。
SAX解析器的優勢是解析速度快,佔用內存少;
DOM在內存中以樹形結構存放,所以檢索和更新效率會更高。可是對於特別大的文檔,解析和加載整個文檔將會很耗資源,不適合移動端;
PULL解析器的運行方式和SAX相似,都是基於事件的模式,PULL解析器小巧輕便,解析速度快,簡單易用,很是適合在Android移動設備中使用,Android系統內部在解析各類XML時也是用PULL解析器。
1 RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,也會調用子View2次onMeasure
2 RelativeLayout的子View若是高度和RelativeLayout不一樣,則會引起效率問題,當子View很複雜時,這個問題會更加嚴重。若是能夠,儘可能使用padding代替margin。
3 在不影響層級深度的狀況下,使用LinearLayout和FrameLayout而不是RelativeLayout。
最後再思考一下文章開頭那個矛盾的問題,爲何Google給開發者默認新建了個RelativeLayout,而本身卻在DecorView中用了個LinearLayout。由於DecorView的層級深度是已知並且固定的,上面一個標題欄,下面一個內容欄。採用RelativeLayout並不會下降層級深度,因此此時在根節點上用LinearLayout是效率最高的。而之因此給開發者默認新建了個RelativeLayout是但願開發者能採用儘可能少的View層級來表達佈局以實現性能最優,由於複雜的View嵌套對性能的影響會更大一些。
<include />
標籤把複雜的界面須要抽取出來<merge />
標籤,由於它在優化UI結構時起到很重要的做用。目的是經過刪減多餘或者額外的層級,從而優化整個Android Layout的結構。核心功能就是減小冗餘的層次從而達到優化UI的目的!它只是用來放啓動圖標的,好處就是,你只用放一個mipmap圖標,它就會給你各類版本(好比平板,手機)的apk自動生成相應分辨率的圖標,以節約空間。
重用converView: 經過複用converview來減小沒必要要的view的建立,另外Infalte操做會把xml文件實例化成相應的View實例,屬於IO操做,是耗時操做。
減小findViewById()操做: 將xml文件中的元素封裝成viewholder靜態類,經過converview的setTag和getTag方法將view與相應的holder對象綁定在一塊兒,避免沒必要要的findviewbyid操做
避免在 getView 方法中作耗時的操做: 例如加載本地 Image 須要載入內存以及解析 Bitmap ,都是比較耗時的操做,若是用戶快速滑動listview,會由於getview邏輯過於複雜耗時而形成滑動卡頓現象。用戶滑動時候不要加載圖片,待滑動完成再加載,可使用這個第三方庫glide
Item的佈局層次結構儘可能簡單,避免佈局太深或者沒必要要的重繪
儘可能能保證 Adapter 的 hasStableIds() 返回 true 這樣在 notifyDataSetChanged() 的時候,若是item內容並無變化,ListView 將不會從新繪製這個 View,達到優化的目的
在一些場景中,ScollView內會包含多個ListView,能夠把listview的高度寫死固定下來。 因爲ScollView在快速滑動過程當中須要大量計算每個listview的高度,阻塞了UI線程致使卡頓現象出現,若是咱們每個item的高度都是均勻的,能夠經過計算把listview的高度肯定下來,避免卡頓現象出現
使用 RecycleView 代替listview: 每一個item內容的變更,listview都須要去調用notifyDataSetChanged來更新所有的item,太浪費性能了。RecycleView能夠實現當個item的局部刷新,而且引入了增長和刪除的動態效果,在性能上和定製上都有很大的改善
ListView 中元素避免半透明: 半透明繪製須要大量乘法計算,在滑動時不停重繪會形成大量的計算,在比較差的機子上會比較卡。 在設計上能不半透明就不不半透明。實在要弄就把在滑動的時候把半透明設置成不透明,滑動完再從新設置成半透明。
儘可能開啓硬件加速: 硬件加速提高巨大,避免使用一些不支持的函數致使含淚關閉某個地方的硬件加速。固然這一條不僅是對 ListView。
這個是考靜態內部類和非靜態內部類的主要區別之一。非靜態內部類會隱式持有外部類的引用,就像你們常常將自定義的adapter在Activity類裏,而後在adapter類裏面是能夠隨意調用外部activity的方法的。當你將內部類定義爲static時,你就調用不了外部類的實例方法了,由於這時候靜態內部類是不持有外部類的引用的。聲明ViewHolder靜態內部類,能夠將ViewHolder和外部類解引用。你們會說通常ViewHolder都很簡單,不定義爲static也沒事吧。確實如此,可是若是你將它定義爲static的,說明你懂這些含義。萬一有一天你在這個ViewHolder加入一些複雜邏輯,作了一些耗時工做,那麼若是ViewHolder是非靜態內部類的話,就很容易出現內存泄露。若是是靜態的話,你就不能直接引用外部類,迫使你關注如何避免相互引用。 因此將 ViewHolder內部類 定義爲靜態的,是一種好習慣
AIDL全程是Android Interface Definition Language,用於生成兩個進程之間通訊(IPC)的代碼.
代理
不少人吧Binder的原理解釋的很複雜,讓人看着就頭大,可是熟悉Linux開發的小夥伴能夠一下想到Binder驅動本質就是文件,實現採用了代理而已.具體看下圖:
逐幀動畫(Drawable Animation): 加載一系列Drawable資源來建立動畫,簡單來講就是播放一系列的圖片來實現動畫效果,能夠自定義每張圖片的持續時間
補間動畫(Tween Animation): Tween能夠對View對象實現一系列簡單的動畫效果,好比位移,縮放,旋轉,透明度等等。可是它並不會改變View屬性的值,只是改變了View的繪製的位置,好比,一個按鈕在動畫事後,不在原來的位置,可是觸發點擊事件的仍然是原來的座標。
屬性動畫(Property Animation): 動畫的對象除了傳統的View對象,還能夠是Object對象,動畫結束後,Object對象的屬性值被實實在在的改變了
Animation框架定義了透明度,旋轉,縮放和位移幾種常見的動畫,並且控制的是整個View,實現原理是每次繪製視圖時View所在的ViewGroup中的drawChild函數獲取該View的Animation的Transformation值,而後調用canvas.concat(transformToApply.getMatrix()),經過矩陣運算完成動畫幀,若是動畫沒有完成,繼續調用invalidate()函數,啓動下次繪製來驅動動畫,動畫過程當中的幀之間間隙時間是繪製函數所消耗的時間,可能會致使動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,並不能相應事件
若是你的需求中只須要對View進行移動、縮放、旋轉和淡入淡出操做,那麼補間動畫確實已經足夠健全了。可是很顯然,這些功能是不足以覆蓋全部的場景的,一旦咱們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操做,那麼補間動畫就不能再幫咱們忙了,也就是說它在功能和可擴展方面都有至關大的侷限性,那麼下面咱們就來看看補間動畫所不能勝任的場景。
注意上面我在介紹補間動畫的時候都有使用「對View進行操做」這樣的描述,沒錯,補間動畫是隻可以做用在View上的。也就是說,咱們能夠對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操做,可是若是咱們想要對一個非View的對象進行動畫操做,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會須要對一個非View的對象進行動畫操做呢?這裏我舉一個簡單的例子,好比說咱們有一個自定義的View,在這個View當中有一個Point對象用於管理座標,而後在onDraw()方法當中就是根據這個Point對象的座標值來進行繪製的。也就是說,若是咱們能夠對Point對象進行動畫操做,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具有這個功能的,這是它的第一個缺陷。
而後補間動畫還有一個缺陷,就是它只可以實現移動、縮放、旋轉和淡入淡出這四種動畫操做,那若是咱們但願能夠對View的背景色進行動態地改變呢?很遺憾,咱們只能靠本身去實現了。說白了,以前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。
最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?好比說,如今屏幕的左上角有一個按鈕,而後咱們經過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,由於實際上這個按鈕仍是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪製到了屏幕的右下角而已。
SurfaceView中採用了雙緩存技術,在單獨的線程中更新界面
View在UI線程中更新界面
measure()方法,layout(),draw()三個方法主要存放了一些標識符,來判斷每一個View是否須要再從新測量,佈局或者繪製,主要的繪製過程仍是在onMeasure,onLayout,onDraw這個三個方法中
1.onMesarue() 爲整個View樹計算實際的大小,即設置實際的高(對應屬性:mMeasuredHeight)和寬(對應屬性: mMeasureWidth),每一個View的控件的實際寬高都是由父視圖和自己視圖決定的。
2.onLayout() 爲將整個根據子視圖的大小以及佈局參數將View樹放到合適的位置上。
3. onDraw() 開始繪製圖像,繪製的流程以下
自定義一個view時,重寫onDraw。調用view.invalidate(),會觸發onDraw和computeScroll()。前提是該view被附加在當前窗口. view.postInvalidate(); //是在非UI線程上調用的
自定義一個ViewGroup,重寫onDraw。onDraw可能不會被調用,緣由是須要先設置一個背景(顏色或圖)。表示這個group有東西須要繪製了,纔會觸發draw,以後是onDraw。所以,通常直接重寫dispatchDraw來繪製viewGroup.自定義一個ViewGroup,dispatchDraw會調用drawChild.
1. 全部Touch事件都被封裝成了MotionEvent對象,包括Touch的位置、時間、歷史記錄以及第幾個手指(多指觸摸)等。
2. 事件類型分爲ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每一個事件都是以ACTION_DOWN開始ACTION_UP結束。
3. 對事件的處理包括三類,分別爲傳遞——dispatchTouchEvent()
函數、攔截——onInterceptTouchEvent()
函數、消費——onTouchEvent()
函數和OnTouchListener()
事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被中止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View能夠經過onTouchEvent()對事件進行處理。
事件由父View(ViewGroup)傳遞給子View,ViewGroup能夠經過onInterceptTouchEvent()對事件作攔截,中止其往下傳遞。
若是事件從上往下傳遞過程當中一直沒有被中止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)能夠進行消費,若是仍是沒有被消費的話,最後會到Activity的onTouchEvent()函數。
若是View沒有對ACTION_DOWN進行消費,以後的其餘事件不會傳遞過來。
OnTouchListener優先於onTouchEvent()對事件進行消費。
上面的消費即表示相應函數返回值爲true。
onTouch優於onTouchEvent,onTouchEvent優於onClick
相關的滑動組件 重寫onInterceptTouchEvent,而後判斷根據xy值,來決定是否要攔截當前操做
Bitmap是android中常用的一個類,它表明了一個圖片資源。 Bitmap消耗內存很嚴重,若是不注意優化代碼,常常會出現OOM問題,優化方式一般有這麼幾種: 1. 使用緩存; 2. 壓縮圖片; 3. 及時回收;
至於何時須要手動調用recycle,這就看具體場景了,原則是當咱們再也不使用Bitmap時,須要回收。另外,咱們須要注意,2.3以前Bitmap對象與像素數據是分開存放的,Bitmap對象存在Java Heap中而像素數據存放在Native Memory中,這時頗有必要調用recycle回收內存。可是2.3以後,Bitmap對象和像素數據都是存在Heap中,GC能夠回收其內存。
JAVA反射機制是在#運行時#,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。 Java反射機制主要提供瞭如下功能: a)在運行時判斷任意一個對象所屬的類; b)在運行時構造任意一個類的對象; c)在運行時判斷任意一個類所具備的成員變量和方法; d)在運行時調用任意一個對象的方法;生成動態代理。
NDK是一些列工具的集合,
NDK提供了一系列的工具,幫助開發者迅速的開發C/C++的動態庫,並能自動將so和java 應用打成apk包。
NDK集成了交叉編譯器,並提供了相應的mk文件和隔離cpu、平臺等的差別,開發人員只需簡單的修改mk文件就能夠建立出so
[https://developer.android.com/training/articles/perf-jni.html]
Java的String和C++的string是不能對等起來的,因此當咱們拿到.h文件下面的jstring對象,會作一次轉換咱們把jstring轉換爲C下面的char*類型, 獲取值
constchar* str;
str = env->GetStringUTFChars(prompt,false);
賦予值
char* tmpstr ="return string succeeded";
jstring rtstr = env->NewStringUTF(tmpstr);
[http://blog.csdn.net/column/details/simple-net.html]
點擊activity上的一個按鈕,發送網絡請求,在網絡比較慢的狀況下,用戶可能會繼續去點擊按鈕,這個時候,發送其餘無謂的請求,不知道你們是怎麼處理這類問題來攔截?
HTTP header中加入max-age,這樣某個固定的時間內都將返回empty body,固然這個方法是死的,把時間徹底限制了,這個方法回掉也會一樣要執行屢次。
還有個暈招,就是直接設置按鈕的clickable爲false,或者使用progressbar,相似於樓主的方法,好比點讚的場景。
使用Map的話,在回掉的時候,仍是須要回收HashMap的,維護Map還不如只維護一個boolean呢。
Volley中若是開了緩存的話, 相同的請求同時只會有一個去真正的請求, 後續都走緩存, 雖然不會請求屢次, 可是回調是會執行屢次的, 和這個需求不match
參考:[http://blog.csdn.net/asce1885/article/details/7844159]
Debug
Log
內存分析:mat,ddms,leakcanary
靜態分析:find bugs
壓力測試:monkey
自動化測試:UIAutomatorMonkeyRunner,Rubotium
類的靜態變量持有大數據對象 靜態變量長期維持到大數據對象的引用,阻止垃圾回收。
非靜態內部類存在靜態實例 非靜態內部類會維持一個到外部類實例的引用,若是非靜態內部類的實例是靜態的,就會間接長期維持着外部類的引用,阻止被回收掉。
資源對象未關閉 資源性對象好比(Cursor,File文件等)每每都用了一些緩衝,咱們在不使用的時候,應該及時關閉它們, 以便它們的緩衝及時回收內存。它們的緩衝不只存在於java虛擬機內,還存在於java虛擬機外。 若是咱們僅僅是把它的引用設置爲null,而不關閉它們,每每會形成內存泄露。 解決辦法: 好比SQLiteCursor(在析構函數finalize(),若是咱們沒有關閉它,它本身會調close()關閉), 若是咱們沒有關閉它,系統在回收它時也會關閉它,可是這樣的效率過低了。 所以對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,而後才置爲null. 在咱們的程序退出時必定要確保咱們的資源性對象已經關閉。 程序中常常會進行查詢數據庫的操做,可是常常會有使用完畢Cursor後沒有關閉的狀況。若是咱們的查詢結果集比較小, 對內存的消耗不容易被發現,只有在常時間大量操做的狀況下才會復現內存問題,這樣就會給之後的測試和問題排查帶來困難和風險,記得try catch後,在finally方法中關閉鏈接
Handler內存泄漏 Handler做爲內部類存在於Activity中,可是Handler生命週期與Activity生命週期每每並非相同的,好比當Handler對象有Message在排隊,則沒法釋放,進而致使本該釋放的Acitivity也沒有辦法進行回收。 解決辦法:
一些不良代碼習慣 有些代碼並不形成內存泄露,可是他們的資源沒有獲得重用,頻繁的申請內存和銷燬內存,消耗CPU資源的同時,也引發內存抖動 解決方案 若是須要頻繁的申請內存對象和和釋放對象,能夠考慮使用對象池來增長對象的複用。 例如ListView即是採用這種思想,經過複用converview來避免頻繁的GC
參見:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html
1. 使用更加輕量的數據結構 例如,咱們能夠考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構。一般的HashMap的實現方式更加消耗內存,由於它須要一個額外的實例對象來記錄Mapping操做。另外,SparseArray更加高效,在於他們避免了對key與value的自動裝箱(autoboxing),而且避免了裝箱後的解箱。
2. 避免在Android裏面使用Enum Android官方培訓課程提到過「Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.」,具體原理請參考《Android性能優化典範(三)》,因此請避免在Android裏面使用到枚舉。
3. 減少Bitmap對象的內存佔用 Bitmap是一個極容易消耗內存的大胖子,減少建立出來的Bitmap的內存佔用可謂是重中之重,,一般來講有如下2個措施: inSampleSize:縮放比例,在把圖片載入內存以前,咱們須要先計算出一個合適的縮放比例,避免沒必要要的大圖載入。 decode format:解碼格式,選擇ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差別
4.Bitmap對象的複用 縮小Bitmap的同時,也須要提升BitMap對象的複用率,避免頻繁建立BitMap對象,複用的方法有如下2個措施 LRUCache : 「最近最少使用算法」在Android中有極其廣泛的應用。ListView與GridView等顯示大量圖片的控件裏,就是使用LRU的機制來緩存處理好的Bitmap,把近期最少使用的數據從緩存中移除,保留使用最頻繁的數據, inBitMap高級特性:利用inBitmap的高級特性提升Android系統在Bitmap分配與釋放執行效率。使用inBitmap屬性能夠告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的Bitmap會嘗試去使用以前那張Bitmap在Heap中所佔據的pixel data內存區域,而不是去問內存從新申請一塊區域來存放Bitmap。利用這種特性,即便是上千張的圖片,也只會僅僅只須要佔用屏幕所可以顯示的圖片數量的內存大小
4. 使用更小的圖片 在涉及給到資源圖片時,咱們須要特別留意這張圖片是否存在能夠壓縮的空間,是否可使用更小的圖片。儘可能使用更小的圖片不只能夠減小內存的使用,還能避免出現大量的InflationException。假設有一張很大的圖片被XML文件直接引用,頗有可能在初始化視圖時會由於內存不足而發生InflationException,這個問題的根本緣由實際上是發生了OOM。
5.StringBuilder 在有些時候,代碼中會須要使用到大量的字符串拼接的操做,這種時候有必要考慮使用StringBuilder來替代頻繁的「+」。
4.避免在onDraw方法裏面執行對象的建立 相似onDraw等頻繁調用的方法,必定須要注意避免在這裏作建立對象的操做,由於他會迅速增長內存的使用,並且很容易引發頻繁的gc,甚至是內存抖動。
5. 避免對象的內存泄露 android中內存泄漏的場景以及解決辦法,參考上一問
ANR全稱Application Not Responding,意思就是程序未響應。若是一個應用沒法響應用戶的輸入,系統就會彈出一個ANR對話框,用戶能夠自行選擇繼續等待亦或者是中止當前程序。一旦出現下面兩種狀況,則彈出ANR對話框
1. 應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸)
2. BroadcastReceiver未在10秒內完成相關的處理
Service在特定的時間內沒法處理完成
超時的緣由通常有兩種:
(1)當前的事件沒有機會獲得處理(UI線程正在處理前一個事件沒有及時完成或者looper被某種緣由阻塞住)
(2)當前的事件正在處理,但沒有及時完成
UI線程儘可能只作跟UI相關的工做,耗時的工做(數據庫操做,I/O,鏈接網絡或者其餘可能阻礙UI線程的操做)放入單獨的線程處理,儘可能用Handler來處理UI thread和thread之間的交互。
UI線程主要包括以下:
• Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick()
• AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel()
• Mainthread handler: handleMessage(), post(runnable r)
開發機器上,查看/data/anr/traces.text.最新的ANR信息在最開始部分.
避免ANR最核心的一點就是在主線程減小耗時操做.一般須要從如下幾個方案下手:
使用子線程處理耗時IO操做。
下降子線程優先級使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,不然仍然會下降程序響應,由於默認Thread的優先級和主線程相同。
使用Handler處理子線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。
Activity的onCreate和onResume回調中儘可能避免耗時的代碼
BroadcastReceiver中onReceive代碼也要儘可能減小耗時操做建議使用IntentService處理。IntentService是一個異步的,會自動中止的服務,很好解決了傳統的Service中處理完耗時操做忘記中止並銷燬Service的問題
密碼不要存在本地,通常保存token。最基本的要代碼混淆,能夠的話加殼,防止反編譯
參考:[http://blog.csdn.net/lijun952048910/article/details/7980562]
Dalvik虛擬機是Android平臺的核心。它能夠支持.dex格式的程序的運行,.dex格式是專爲Dalvik設計的一種壓縮格式,能夠減小總體文件尺寸,提升I/O操做的速度,適合內存和處理器速度有限的系統
通常是16m或者24m,可是能夠經過android:largeHeap申請更多內存,具體參考:
[https://liuzhichao.com/2016/use-android_largeHeap.html]
[http://www.cnblogs.com/mythou/p/3203536.html]
使用Android Studio 的gradle 能夠構建MutilDex
總結 linux啓動->init進程啓動(加載init.rc配置)->zygote啓動->systemServer啓動,systemServer會經過init1和init2啓動navite世界和java世界_