Android高級開發面試題目,媽媽不再用擔憂我不能升職加薪了!

**Java基礎
一、內部類的做用**html

內部類能夠用多個實例,每一個實例都有本身的狀態信息,而且與其餘外圍對象的信息相互獨立。java

在單個外部類中,可讓多個內部類以不一樣的方式實現同一個接口,或者繼承同一個類。android

建立內部類對象的時刻並不依賴於外圍類對象的建立。面試

內部類並無使人迷惑的「is-a」關係,他就是一個獨立的實體。算法

內部類提供了更好的封裝,除了該外圍類,其餘類都不能訪問數據庫

二、父類的靜態方法可否被子類重寫,爲何?編程

不能小程序

子類繼承父類後,用相同的靜態方法和非靜態方法,這時非靜態方法覆蓋父類中的方法(即方法重寫),父類的該靜態方法被隱藏(若是對象是父類則調用該隱藏的方法),另外子類可繼承父類的靜態與非靜態方法,至於方法重載我以爲它其中一要素就是在同一類中,不能說父類中的什麼方法與子類裏的什麼方法是方法重載的體現設計模式

想學習更多Android知識,或者獲取相關資料請加入Android技術開發交流2羣:862625886。本羣可免費獲取Gradle、RxJava、小程序、Hybrid、移動架構、NDK、React Native、性能優化等技術教程!數組

三、哪些狀況下的對象會被垃圾回收機制處理掉

Java垃圾回收機制最基本的作法是分代回收。內存中的區域被劃分紅不一樣的世代,對象根據其存活的時間被保存在對應世代的區域中。通常的實現是劃分紅3個世代:年輕、年老和永久。內存的分配是發生在年輕世代中的。當一個對象存活時間足夠長的時候,它就會被複制到年老世代中。對於不一樣的世代可使用不一樣的垃圾回收算法。進行世代劃分的出發點是對應用中對象存活時間進行研究以後得出的統計規律。通常來講,一個應用中的大部分對象的存活時間都很短。好比局部變量的存活時間就只在方法的執行過程當中。基於這一點,對於年輕世代的垃圾回收算法就能夠頗有針對性。
四、進程和線程的區別

簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。

線程的劃分尺度小於進程,使得多線程程序的併發性高。

另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。

線程在執行過程當中與進程仍是有區別的。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分能夠同時執行。但操做系統並無將多個線程看作多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程是具備必定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程本身基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),可是它可與同屬一個進程的其餘的線程共享進程所擁有的所有資源.

一個線程能夠建立和撤銷另外一個線程;同一個進程中的多個線程之間能夠併發執行.

進程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。若是有興趣深刻的話,我建議大家看看《現代操做系統》或者《操做系統的設計與實現》。對就個問題說得比較清楚。

五、HashMap的實現原理

HashMap概述:HashMap是基於哈希表的Map接口的非同步實現。此實現提供全部可選的映射操做,並容許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恆久不變。

HashMap的數據結構:在java編程語言中,最基本的結構就是兩種,一個是數組,另一個是模擬指針(引用),全部的數據結構均可以用這兩個基本結構來構造的,HashMap也不例外。HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。

HashMap底層就是一個數組結構,數組中的每一項又是一個鏈表。當新建一個HashMap的時候,就會初始化一個數組。

六、String、StringBuffer、StringBuilder區別

String 字符串常量

StringBuffer 字符串變量(線程安全)

StringBuilder 字符串變量(非線程安全)

簡要的說, String 類型和 StringBuffer 類型的主要性能區別其實在於 String 是不可變的對象, 所以在每次對 String 類型進行改變的時候其實都等同於生成了一個新的 String 對象,而後將指針指向新的 String 對象,因此常常改變內容的字符串最好不要用String ,由於每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了之後,JVM 的 GC 就會開始工做,那速度是必定會至關慢的。

而若是是使用 StringBuffer 類則結果就不同了,每次結果都會對 StringBuffer 對象自己進行操做,而不是生成新的對象,再改變對象引用。因此在通常狀況下咱們推薦使用 StringBuffer ,特別是字符串對象常常改變的狀況下。而在某些特別狀況下, String 對象的字符串拼接實際上是被 JVM 解釋成了 StringBuffer 對象的拼接,因此這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是如下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的:

在大部分狀況下 StringBuffer > String

Java.lang.StringBuffer線程安全的可變字符序列。一個相似於 String 的字符串緩衝區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但經過某些方法調用能夠改變該序列的長度和內容。

可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致。

StringBuffer 上的主要操做是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每一個方法都能有效地將給定的數據轉換成字符串,而後將該字符串的字符追加或插入到字符串緩衝區中。append 方法始終將這些字符添加到緩衝區的末端;而 insert 方法則在指定的點添加字符。

在大部分狀況下 StringBuilder > StringBuffer

java.lang.StringBuilder一個可變的字符序列是5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用做 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。若是可能,建議優先採用該類,由於在大多數實現中,它比 StringBuffer 要快。二者的方法基本相同
七、什麼致使線程阻塞

線程的阻塞

爲了解決對共享存儲區的訪問衝突,Java 引入了同步機制,如今讓咱們來考察多個線程對共享資源的訪問,顯然同步機制已經不夠了,由於在任意時刻所要求的資源不必定已經準備好了被訪問,反過來,同一時刻準備好了的資源也可能不止一個。爲了解決這種狀況下的訪問控制問題,Java 引入了對阻塞機制的支持.

阻塞指的是暫停一個線程的執行以等待某個條件發生(如某資源就緒),學過操做系統的同窗對它必定已經很熟悉了。Java 提供了大量方法來支持阻塞,下面讓咱們逐一分析。

sleep() 方法:sleep() 容許 指定以毫秒爲單位的一段時間做爲參數,它使得線程在指定的時間內進入阻塞狀態,不能獲得CPU 時間,指定的時間一過,線程從新進入可執行狀態。 典型地,sleep() 被用在等待某個資源就緒的情形:測試發現條件不知足後,讓線程阻塞一段時間後從新測試,直到條件知足爲止。

suspend() 和 resume() 方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,而且不會自動恢復,必須其對應的resume() 被調用,才能使得線程從新進入可執行狀態。典型地,suspend() 和 resume() 被用在等待另外一個線程產生的結果的情形:測試發現結果尚未產生後,讓線程阻塞,另外一個線程產生告終果後,調用 resume() 使其恢復。

yield() 方法:yield() 使得線程放棄當前分得的 CPU 時間,可是不使線程阻塞,即線程仍處於可執行狀態,隨時可能再次分得 CPU 時間。調用 yield() 的效果等價於調度程序認爲該線程已執行了足夠的時間從而轉到另外一個線程.

wait() 和 notify() 方法:兩個方法配套使用,wait() 使得線程進入阻塞狀態,它有兩種形式,一種容許 指定以毫秒爲單位的一段時間做爲參數,另外一種沒有參數,前者當對應的 notify() 被調用或者超出指定時間時線程從新進入可執行狀態,後者則必須對應的 notify() 被調用.

初看起來它們與 suspend() 和 resume() 方法對沒有什麼分別,可是事實上它們是大相徑庭的。區別的核心在於,前面敘述的全部方法,阻塞時都不會釋放佔用的鎖(若是佔用了的話),而這一對方法則相反。

首先,前面敘述的全部方法都隸屬於 Thread 類,可是這一對卻直接隸屬於 Object 類,也就是說,全部對象都擁有這一對方法。初看起來這十分難以想象,可是實際上倒是很天然的,由於這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具備的,調用任意對象的 wait() 方法致使線程阻塞,而且該對象上的鎖被釋放。而調用 任意對象的notify()方法則致使因調用該對象的 wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到得到鎖後才真正可執行)。

其次,前面敘述的全部方法均可在任何位置調用,可是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在synchronized 方法或塊中當前線程才佔有鎖,纔有鎖能夠釋放。一樣的道理,調用這一對方法的對象上的鎖必須爲當前線程所擁有,這樣纔有鎖能夠釋放。所以,這一對方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的上鎖對象就是調用這一對方法的對象。若不知足這一條件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。

wait() 和 notify() 方法的上述特性決定了它們常常和synchronized方法或塊一塊兒使用,將它們和操做系統的進程間通訊機制做一個比較就會發現它們的類似性:synchronized方法或塊提供了相似於操做系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則至關於 block 和wakeup 原語(這一對方法均聲明爲 synchronized)。它們的結合使得咱們能夠實現操做系統上一系列精妙的進程間通訊的算法(如信號量算法),並用於解決各類複雜的線程間通訊問題。

關於 wait() 和 notify() 方法最後再說明兩點:

a、調用 notify() 方法致使解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,咱們沒法預料哪個線程將會被選擇,因此編程時要特別當心,避免因這種不肯定性而產生問題。

b、除了 notify(),還有一個方法 notifyAll() 也可起到相似做用,惟一的區別在於,調用 notifyAll() 方法將把因調用該對象的 wait() 方法而阻塞的全部線程一次性所有解除阻塞。固然,只有得到鎖的那一個線程才能進入可執行狀態。

**Android基礎
一、是否使用過IntentService,做用是什麼,AIDL解決了什麼問題?**

生成一個默認的且與主線程互相獨立的工做者線程來執行全部傳送至onStartCommand() 方法的Intetnt。

生成一個工做隊列來傳送Intent對象給你的onHandleIntent()方法,同一時刻只傳送一個Intent對象,這樣一來,你就沒必要擔憂多線程的問題。在全部的請求(Intent)都被執行完之後會自動中止服務,因此,你不須要本身去調用stopSelf()方法來中止。

該服務提供了一個onBind()方法的默認實現,它返回null

提供了一個onStartCommand()方法的默認實現,它將Intent先傳送至工做隊列,而後從工做隊列中每次取出一個傳送至onHandleIntent()方法,在該方法中對Intent對相應的處理。

AIDL (Android Interface Definition Language) 是一種IDL 語言,用於生成能夠在Android設備上兩個進程之間進行進程間通訊(interprocess communication, IPC)的代碼。若是在一個進程中(例如Activity)要調用另外一個進程中(例如Service)對象的操做,就可使用AIDL生成可序列化的參數。 AIDL IPC機制是面向接口的,像COM或Corba同樣,可是更加輕量級。它是使用代理類在客戶端和實現端傳遞數據。

二、Activity、Window、View三者的差異?

Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。

在Activity中調用attach,建立了一個Window

建立的window是其子類PhoneWindow,在attach中建立PhoneWindow

在Activity中調用setContentView(R.layout.xxx)

其中其實是調用的getWindow().setContentView()

調用PhoneWindow中的setContentView方法

建立ParentView: 做爲ViewGroup的子類,實際是建立的DecorView(做爲FramLayout的子類)

將指定的R.layout.xxx進行填充 經過佈局填充器進行填充【其中的parent指的就是DecorView】

調用到ViewGroup

調用ViewGroup的removeAllView(),先將全部的view移除掉

添加新的view:addView()

三、Fragment 特色

Fragment能夠做爲Activity界面的一部分組成出現;

能夠在一個Activity中同時出現多個Fragment,而且一個Fragment也能夠在多個Activity中使用;

在Activity運行過程當中,能夠添加、移除或者替換Fragment;

Fragment能夠響應本身的輸入事件,而且有本身的生命週期,它們的生命週期會受宿主Activity的生命週期影響。

四、Handler、Thread和HandlerThread的差異?

http://blog.csdn.net/guolin_b...

http://droidyue.com/blog/2015...

從Android中Thread(java.lang.Thread -> java.lang.Object)描述能夠看出,Android的Thread沒有對Java的Thread作任何封裝,可是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread作了不少便利Android系統的封裝。

android.os.Handler能夠經過Looper對象實例化,並運行於另外的線程中,Android提供了讓Handler運行於其它線程的線程實現,也就是HandlerThread。HandlerThread對象start後能夠得到其Looper對象,而且使用這個Looper對象實例Handler。

五、Launch mode應用場景

Standard,建立一個新的Activity。

SingleTop,棧頂不是該類型的Activity,建立一個新的Activity。不然,onNewIntent。

SingleTask,回退棧中沒有該類型的Activity,建立Activity,不然,onNewIntent+ClearTop。

注意:

設置了"singleTask"啓動模式的Activity,它在啓動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的Task存在; 若是存在這樣的Task,它就會在這個Task中啓動,不然就會在新的任務棧中啓動。所以, 若是咱們想要設置了"singleTask"啓動模式的Activity在新的任務中啓動,就要爲它設置一個獨立的taskAffinity屬性值。

若是設置了"singleTask"啓動模式的Activity不是在新的任務中啓動時,它會在已有的任務中查看是否已經存在相應的Activity實例, 若是存在,就會把位於這個Activity實例上面的Activity所有結束掉,即最終這個Activity 實例會位於任務的Stack頂端中。

在一個任務棧中只有一個」singleTask」啓動模式的Activity存在。他的上面能夠有其餘的Activity。這點與singleInstance是有區別的。

singleInstance,回退棧中,只有這一個Activity,沒有其餘Activity。

SingleTop適合接收通知啓動的內容顯示頁面。

例如,某個新聞客戶端的新聞內容頁面,若是收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。

singleTask適合做爲程序入口點。

例如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent,而且會清空主界面上面的其餘頁面。

singleInstance應用場景:

鬧鈴的響鈴界面。 你之前設置了一個鬧鈴:上午6點。在上午5點58分,你啓動了鬧鈴設置界面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天;在6點時,鬧鈴響了,而且彈出了一個對話框形式的 Activity(名爲 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵,回到的是微信的聊天界面,這是由於 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 所以退出以後這個 Task 的棧空了。若是是以 SingleTask 打開 AlarmAlertActivity,那麼當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設置界面。

六、Android事件分發機制

https://www.jianshu.com/p/380...
七、view繪製流程

https://www.jianshu.com/p/bb7...
八、post和postDelay

九、線程同步

http://www.itzhai.com/java-ba...

推薦:Android開發面試題彙總

[收集的Android面試題,有時間看看~一、 Android dvm的進程和Linux的進程, 應用程序的進程是否爲同一個概念DVM指Dalvik的虛擬機。每個Android應用程序都在它本身的進程中

http://www.juwends.com/tech/a...

十、單例模式

public class Singleton {
private volatile static Singleton mSingleton;
private Singleton () {
}
public static Singleton getInstance () {
if (mSingleton == null ){
synchronized (Singleton.class){
if (mSingleton == null )
mSingleton = new Singleton();
}
}
return mSingleton;
}
}

十一、什麼狀況致使內存泄漏

a、資源對象沒關閉形成的內存泄漏

描述: 資源性對象好比(Cursor,File文件等)每每都用了一些緩衝,咱們在不使用的時候,應該及時關閉它們,以便它們的緩衝及時回收內存。它們的緩衝不只存在於 java虛擬機內,還存在於java虛擬機外。若是咱們僅僅是把它的引用設置爲null,而不關閉它們,每每會形成內存泄漏。由於有些資源性對象,好比 SQLiteCursor(在析構函數finalize(),若是咱們沒有關閉它,它本身會調close()關閉),若是咱們沒有關閉它,系統在回收它時也會關閉它,可是這樣的效率過低了。所以對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,而後才置爲null.在咱們的程序退出時必定要確保咱們的資源性對象已經關閉。 程序中常常會進行查詢數據庫的操做,可是常常會有使用完畢Cursor後沒有關閉的狀況。若是咱們的查詢結果集比較小,對內存的消耗不容易被發現,只有在常時間大量操做的狀況下才會復現內存問題,這樣就會給之後的測試和問題排查帶來困難和風險。

b、構造Adapter時,沒有使用緩存的convertView

以構造ListView的BaseAdapter爲例,在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 來向ListView提供每個item所須要的view對象。初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化必定數量的 view對象,同時ListView會將這些view對象緩存起來。當向上滾動ListView時,原先位於最上面的list item的view對象會被回收,而後被用來構造新出現的最下面的list item。這個構造過程就是由getView()方法完成的,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。由此能夠看出,若是咱們不去使用 convertView,而是每次都在getView()中從新實例化一個View對象的話,即浪費資源也浪費時間,也會使得內存佔用愈來愈大。 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;
}

c、Bitmap對象不在使用時調用recycle()釋放內存

有時咱們會手工的操做Bitmap對象,若是一個Bitmap對象比較佔內存,當它不在被使用的時候,能夠調用Bitmap.recycle()方法回收此對象的像素所佔用的內存,但這不是必須的,視狀況而定。

d、試着使用關於application的context來替代和activity相關的context

這是一個很隱晦的內存泄漏的狀況。有一種簡單的方法來避免context相關的內存泄漏。最顯著地一個是避免context逃出他本身的範圍以外。使用Application context。這個context的生存週期和你的應用的生存週期同樣長,而不是取決於activity的生存週期。若是你想保持一個長期生存的對象,而且這個對象須要一個context,記得使用application對象。你能夠經過調用 Context.getApplicationContext() or Activity.getApplication()來得到。更多的請看這篇文章如何避免 Android內存泄漏。

e、註冊沒反註冊形成的內存泄漏

一些Android程序可能引用咱們的Anroid程序的對象(好比註冊機制)。即便咱們的Android程序已經結束了,可是別的引用程序仍然還有對咱們的Android程序的某個對象的引用,泄漏的內存依然不能被垃圾回收。調用registerReceiver後未調用unregisterReceiver。 好比:假設咱們但願在鎖屏界面(LockScreen)中,監聽系統中的電話服務以獲取一些信息(如信號強度等),則能夠在LockScreen中定義一個 PhoneStateListener的對象,同時將它註冊到TelephonyManager服務中。對於LockScreen對象,當須要顯示鎖屏界面的時候就會建立一個LockScreen對象,而當鎖屏界面消失的時候LockScreen對象就會被釋放掉。 可是若是在釋放 LockScreen對象的時候忘記取消咱們以前註冊的PhoneStateListener對象,則會致使LockScreen沒法被垃圾回收。若是不斷的使鎖屏界面顯示和消失,則最終會因爲大量的LockScreen對象沒有辦法被回收而引發OutOfMemory,使得system_process 進程掛掉。 雖然有些系統程序,它自己好像是能夠自動取消註冊的(固然不及時),可是咱們仍是應該在咱們的程序中明確的取消註冊,程序結束時應該把全部的註冊都取消掉。

f、集合中對象沒清理形成的內存泄漏

咱們一般把一些對象的引用加入到了集合中,當咱們不須要該對象時,並無把它的引用從集合中清理掉,這樣這個集合就會愈來愈大。若是這個集合是static的話,那狀況就更嚴重了

十二、ANR定位和如何避免?

1.若是開發機器上出現問題,咱們能夠經過查看/data/anr/traces.txt便可,最新的ANR信息在最開始部分。

2.主線程被IO操做(從4.0以後網絡IO不容許在主線程中)阻塞。

3.主線程中存在耗時的計算

4.主線程中錯誤的操做,好比Thread.wait或者Thread.sleep等 Android系統會監控程序的響應情況,一旦出現下面兩種狀況,則彈出ANR對話框

5.應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸)

6.BroadcastReceiver未在10秒內完成相關的處理

7.Service在特定的時間內沒法處理完成 20秒

避免

1.使用AsyncTask處理耗時IO操做。

2.使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,不然仍然會下降程序響應,由於默認Thread的優先級和主線程相同。

3.使用Handler處理工做線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。

4.Activity的onCreate和onResume回調中儘可能避免耗時的代碼

5.BroadcastReceiver中onReceive代碼也要儘可能減小耗時,建議使用IntentService處理。

1三、什麼狀況致使OOM以及如何避免?

http://blog.csdn.net/yangxueh...

http://blog.csdn.net/ljx19900...

1四、Android Service與Activity之間通訊的幾種方式?

經過Binder對象

經過Broadcast(廣播)的形式

1五、如何保證service在後臺儘可能不被kill

onStartCommand方法,返回START_STICKY

1.START_STICKY 在運行onStartCommand後service進程被kill後,那將保留在開始狀態,可是不保留那些傳入的intent。不久後service就會再次嘗試從新建立,由於保留在開始狀態,在建立 service後將保證調用onstartCommand。若是沒有傳遞任何開始命令給service,那將獲取到null的intent。

2.START_NOT_STICKY 在運行onStartCommand後service進程被kill後,而且沒有新的intent傳遞給它。Service將移出開始狀態,而且直到新的明顯的方法(startService)調用才從新建立。由於若是沒有傳遞任何未決定的intent那麼service是不會啓動,也就是期間onstartCommand不會接收到任何null的intent。

3.START_REDELIVER_INTENT 在運行onStartCommand後service進程被kill後,系統將會再次啓動service,並傳入最後一個intent給onstartCommand。直到調用stopSelf(int)才中止傳遞intent。若是在被kill後還有未處理好的intent,那被kill後服務仍是會自動啓動。所以onstartCommand不會接收到任何null的intent。

提高service優先級
在AndroidManifest.xml文件中對於intent-filter能夠經過android:priority="1000"這個屬性設置最高優先級,1000是最高值,若是數字越小則優先級越低,同時適用於廣播。

提高service進程優先級
Android中的進程是託管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。Android將進程分爲6個等級,它們按優先級順序由高到低依次是:

前臺進程( FOREGROUND_APP)
可視進程(VISIBLE_APP )
次要服務進程(SECONDARY_SERVER )
後臺進程 (HIDDEN_APP)
內容供應節點(CONTENT_PROVIDER)
空進程(EMPTY_APP)
當service運行在低內存的環境時,將會kill掉一些存在的進程。所以進程的優先級將會很重要,可使用startForeground 將service放到前臺狀態。這樣在低內存時被kill的概率會低一些。

onDestroy方法裏重啓service
service+broadcast方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,從新啓動service;
Application加上Persistent屬性
監聽系統廣播判斷Service狀態

1六、RequestLayout,onLayout,onDraw,DrawChild區別與聯繫

1.requestLayout()方法 :會致使調用measure()過程 和 layout()過程 。說明:只是對View樹從新佈局layout過程包括measure()和layout()過程,不會調用draw()過程,但不會從新繪製 任何視圖包括該調用者自己。

2.onLayout()方法(若是該View是ViewGroup對象,須要實現該方法,對每一個子視圖進行佈局)

3.調用onDraw()方法繪製視圖自己(每一個View都須要重載該方法,ViewGroup不須要實現該方法)

4.drawChild()去從新回調每一個子視圖的draw()方法

1七、invalidate()和postInvalidate() 的區別及使用

http://blog.csdn.net/mars2639...

1八、LinearLayout對比RelativeLayout

RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,也會調用子View2次onMeasure

RelativeLayout的子View若是高度和RelativeLayout不一樣,則會引起效率問題,當子View很複雜時,這個問題會更加嚴重。若是能夠,儘可能使用padding代替margin。

在不影響層級深度的狀況下,使用LinearLayout和FrameLayout而不是RelativeLayout。

1九、優化自定義view

爲了加速你的view,對於頻繁調用的方法,須要儘可能減小沒必要要的代碼。先從onDraw開始,須要特別注意不該該在這裏作內存分配的事情,由於它會致使GC,從而致使卡頓。在初始化或者動畫間隙期間作分配內存的動做。不要在動畫正在執行的時候作內存分配的事情。

你還須要儘量的減小onDraw被調用的次數,大多數時候致使onDraw都是由於調用了invalidate().所以請儘可能減小調用invaildate()的次數。若是可能的話,儘可能調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。

另一個很是耗時的操做是請求layout。任什麼時候候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每個view的大小。若是找到有衝突的值,它會須要從新計算好幾回。另外須要儘可能保持View的層級是扁平化的,這樣對提升效率頗有幫助。

若是你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操做。與內置的view不一樣,自定義的view可使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展現瞭如何繼承ViewGroup做爲自定義view的一部分。PieChart 有子views,可是它歷來不測量它們。而是根據他自身的layout法則,直接設置它們的大小。

20、ContentProvider

https://www.jianshu.com/p/ea8...

2一、Android 設計模式

http://blog.csdn.net/bboyfeiy...

2二、MVC、MVP、MVM區別?

https://www.cnblogs.com/guwei...

想學習更多Android知識,或者獲取相關資料請加入Android技術開發交流2羣:862625886。本羣可免費獲取Gradle、RxJava、小程序、Hybrid、移動架構、NDK、React Native、性能優化等技術教程!

相關文章
相關標籤/搜索