Andorid面試問題整理

Acitivty的四中啓動模式與特色。

      • standard:默認的啓動模式
      • singleTop:適合那種接受通知啓動的頁面,好比新聞客戶端之類的,可能會給你推送好幾回 ,可是每次都是打開同一張頁面調用onNewIntent
      • singleTask:適合做爲程序入口點,例如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent,而且會清空瀏覽器主界面上面的其餘頁面。而以前打開過的頁面再也不新建
      • singleInstance:適合須要與程序分離開的頁面。例如鬧鈴,將鬧鈴提醒與設置分離,使得鬧鈴提醒成爲系統範圍內的惟一實例

Acitivity後臺閒置退出或異常退出,如何保存數據html

經過 onSaveInstanceState() 和 onRestoreInstanceState() 保存和重啓非持久化數據。java

Service的生命週期,兩種啓動方法,有什麼區別

Service的第一種啓動方式

採用start的方式開啓服務android

使用Service的步驟:web

1.定義一個類繼承Service
2.在Manifest.xml文件中配置該Service
3.使用Context的startService(Intent)方法啓動該Service
4.再也不使用時,調用stopService(Intent)方法中止該服務算法

使用這種start方式啓動的Service的生命週期以下:數據庫

onCreate()—>onStartCommand()(onStart()方法已過期) —> onDestory()json

說明:數組

若是服務已經開啓,不會重複的執行onCreate(), 而是會調用onStart()和onStartCommand()。
服務中止的時候調用 onDestory()。服務只會被中止一次。瀏覽器

特色:緩存

一旦服務開啓跟調用者(開啓者)就沒有任何關係了。
開啓者退出了,開啓者掛了,服務還在後臺長期的運行。
開啓者不能調用服務裏面的方法。

Service的第二種啓動方式

採用bind的方式開啓服務

使用Service的步驟:

1.定義一個類繼承Service
2.在Manifest.xml文件中配置該Service
3.使用Context的bindService(Intent, ServiceConnection, int)方法啓動該Service
4.再也不使用時,調用unbindService(ServiceConnection)方法中止該服務

使用這種start方式啓動的Service的生命週期以下:

onCreate() —>onBind()—>onunbind()—>onDestory()

注意:綁定服務不會調用onstart()或者onstartcommand()方法

特色:bind的方式開啓服務,綁定服務,調用者掛了,服務也會跟着掛掉。
綁定者能夠調用服務裏面的方法。

綁定者如何調用服務裏的方法呢?

首先定義一個Service的子類。

public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
//返回MyBind對象
return new MyBinder();
}
private void methodInMyService() {
Toast.makeText(getApplicationContext(), "服務裏的方法執行了。。。",
Toast.LENGTH_SHORT).show();
}
/**
* 該類用於在onBind方法執行後返回的對象,
* 該對象對外提供了該服務裏的方法
*/
private class MyBinder extends Binder implements IMyBinder {
@Override
public void invokeMethodInMyService() {
methodInMyService();
}
}
}

自定義的MyBinder接口用於保護服務中不想讓外界訪問的方法。

public interface IMyBinder {
void invokeMethodInMyService();
}

接着在Manifest.xml文件中配置該Service
<service android:name=".MyService"/>
在Activity中綁定並調用服務裏的方法
簡單佈局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="start"
android:text="開啓服務"
android:textSize="30sp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="invoke"
android:text="調用服務的方法"
android:textSize="30sp" />
</LinearLayout>

綁定服務的Activity:

public class MainActivity extends Activity {
private MyConn conn;
private Intent intent;
private IMyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//開啓服務按鈕的點擊事件
public void start(View view) {
intent = new Intent(this, MyService.class);
conn = new MyConn();
//綁定服務,
// 第一個參數是intent對象,表面開啓的服務。
// 第二個參數是綁定服務的監聽器
// 第三個參數通常爲BIND_AUTO_CREATE常量,表示自動建立bind
bindService(intent, conn, BIND_AUTO_CREATE);
}
//調用服務方法按鈕的點擊事件
public void invoke(View view) {
myBinder.invokeMethodInMyService();
}
private class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//iBinder爲服務裏面onBind()方法返回的對象,因此能夠強轉爲IMyBinder類型
myBinder = (IMyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
}

綁定本地服務調用方法的步驟:

1.在服務的內部建立一個內部類 提供一個方法,能夠間接調用服務的方法
2.實現服務的onbind方法,返回的就是這個內部類
3.在activity 綁定服務。bindService();
4.在服務成功綁定的回調方法onServiceConnected, 會傳遞過來一個 IBinder對象
5.強制類型轉化爲自定義的接口類型,調用接口裏面的方法。

RxJava&RxAndroid

RxJava 究竟是什麼

異步,簡潔。

RxJava 在 GitHub 主頁上的自我介紹是 「a library for composing asynchronous and event-based programs using observable sequences for the Java VM」(一個在 Java VM 上使用可觀測的序列來組成異步的、基於事件的程序的庫)。這就是 RxJava ,歸納得很是精準。

然而,對於初學者來講,這太難看懂了。由於它是一個『總結』,而初學者更須要一個『引言』。

其實, RxJava 的本質能夠壓縮爲異步這一個詞。說到根上,它就是一個實現異步操做的庫,而別的定語都是基於這之上的。

鏈式調用 線程切換容易 更加符合思惟 不會出現迷之嵌套

 

Intent的使用方法,能夠傳遞哪些數據類型

      • Serializable :
        將 Java 對象序列化爲二進制文件的 Java 序列化技術是 Java系列技術中一個較爲重要的技術點,在大部分狀況下,開發人員只須要了解被序列化的類須要實現 Serializable 接口,使用ObjectInputStream 和 ObjectOutputStream 進行對象的讀寫。
      • charsequence :
        在JDK1.4中,引入了CharSequence接口,實現了這個接口的類有:CharBuffer、String、StringBuffer、StringBuilder這個四個類。
        CharBuffer爲nio裏面用的一個類,String實現這個接口理所固然,StringBuffer也是一個CharSequence,StringBuilder是Java抄襲C#的一個類,基本和StringBuffer類同樣,效率高,可是不保證線程安全,在不須要多線程的環境下能夠考慮。
        提供這麼一個接口,有些處理String或者StringBuffer的類就不用重載了。可是這個接口提供的方法有限,只有下面幾個:charat、length、subSequence、toString這幾個方法,感受若是有必要,仍是重載的比較好,避免用instaneof這個操做符。
      • Parcelable :
        android提供了一種新的類型:Parcel。本類被用做封裝數據的容器,封裝後的數據能夠經過Intent或IPC傳遞。 除了基本類型以
        外,只有實現了Parcelable接口的類才能被放入Parcel中。
        是GOOGLE在安卓中實現的另外一種序列化,功能和Serializable類似,主要是序列化的方式不一樣
      • Bundle:
        Bundle是將數據傳遞到另外一個上下文中或保存或回覆你本身狀態的數據存儲方式。它的數據不是持久化狀態。

能夠直接經過調用Intent的putExtra()方法存入數據,而後在得到Intent後調用getXxxExtra得到 對應類型的數據;傳遞多個的話,可使用Bundle對象做爲容器,經過調用Bundle的putXxx先將數據 存儲到Bundle中,而後調用Intent的putExtras()方法將Bundle存入Intent中,而後得到Intent之後, 調用getExtras()得到Bundle容器,而後調用其getXXX獲取對應的數據! 另外數據存儲有點相似於Map的<鍵,值>!

傳遞對象的方式有兩種:將對象轉換爲Json字符串或者經過Serializable,Parcelable序列化 不建議使用Android內置的摳腳Json解析器,可以使用fastjson或者Gson第三方庫!

ContentProvider使用方法

由於在Android系統裏面,數據庫是私有的。通常狀況下外部應用程序是沒有權限讀取其餘應用程序的數據。若是你想公開你本身的數據,你有兩個選擇:你能夠建立你本身的內容提供器(一個ContentProvider子類)或者你能夠給已有的提供器添加數據-若是存在一個控制一樣類型數據的內容提供器且你擁有寫的權限。而外界根本看不到,也不用看到這個應用暴露的數據在應用當中是如何存儲的,或者是用數據庫存儲仍是用文件存儲,仍是經過網上得到,這些一切都不重要,重要的是外界能夠經過這一套標準及統一的接口和程序裏的數據打交道,能夠讀取程序的數據,也能夠刪除程序的數據,固然,中間也會涉及一些權限的問題。

Thread、AsycTask、IntentService的使用場景與特色。

Android 原生的 AsyncTask.java 是對線程池的一個封裝,使用其自定義的 Executor 來調度線程的執行方式(併發仍是串行),並使用 Handler 來完成子線程和主線程數據的共享。

預先了解 AsyncTask,必先對線程池有所瞭解。通常狀況下,若是使用子線程去執行一些任務,那麼使用 new Thread 的方式會很方便的建立一個線程,若是涉及到主線程和子線程的通訊,咱們將使用 Handler(通常須要刷新 UI 的適合用到)。若是咱們建立大量的(特別是在短期內,持續的建立生命週期較長的線程)野生線程,每每會出現以下兩方面的問題:每一個線程的建立與銷燬(特別是建立)的資源開銷是很是大的;大量的子線程會分享主線程的系統資源,從而會使主線程因資源受限而致使應用性能下降。各位開發一線的前輩們爲了解決這個問題,引入了線程池(ThreadPool)的概念,也就是把這些野生的線程圈養起來,統一的管理他們。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。

使用線程池的風險?

雖然線程池是構建多線程應用程序的強大機制,但使用它並非沒有風險的。用線程池構建的應用程序容易遭受任何其它多線程應用程序容易遭受的全部併發風險,諸如同步錯誤和死鎖,它還容易遭受特定於線程池的少數其它風險,諸如與池有關的死鎖、資源不足和線程泄漏。

      • 死鎖

        任何多線程應用程序都有死鎖風險。當一組進程或線程中的每個都在等待一個只有該組中另外一個進程才能引發的事件時,咱們就說這組進程或線程 死鎖了。死鎖的最簡單情形是:線程 A 持有對象 X 的獨佔鎖,而且在等待對象 Y 的鎖,而線程 B 持有對象 Y 的獨佔鎖,卻在等待對象 X 的鎖。除非有某種方法來打破對鎖的等待(Java 鎖定不支持這種方法),不然死鎖的線程將永遠等下去。

        雖然任何多線程程序中都有死鎖的風險,但線程池卻引入了另外一種死鎖可能,在那種狀況下,全部池線程都在執行已阻塞的等待隊列中另外一任務的執行結果的任務,但這一任務卻由於沒有未被佔用的線程而不能運行。當線程池被用來實現涉及許多交互對象的模擬,被模擬的對象能夠相互發送查詢,這些查詢接下來做爲排隊的任務執行,查詢對象又同步等待着響應時,會發生這種狀況。

      • 資源不足

        線程池的一個優勢在於:相對於其它替代調度機制(有些咱們已經討論過)而言,它們一般執行得很好。但只有恰當地調整了線程池大小時纔是這樣的。線程消耗包括內存和其它系統資源在內的大量資源。除了 Thread 對象所需的內存以外,每一個線程都須要兩個可能很大的執行調用堆棧。除此之外,JVM 可能會爲每一個 Java 線程建立一個本機線程,這些本機線程將消耗額外的系統資源。最後,雖然線程之間切換的調度開銷很小,但若是有不少線程,環境切換也可能嚴重地影響程序的性能。

        若是線程池太大,那麼被那些線程消耗的資源可能嚴重地影響系統性能。在線程之間進行切換將會浪費時間,並且使用超出比您實際須要的線程可能會引發資源匱乏問題,由於池線程正在消耗一些資源,而這些資源可能會被其它任務更有效地利用。除了線程自身所使用的資源之外,服務請求時所作的工做可能須要其它資源,例如 JDBC 鏈接、套接字或文件。這些也都是有限資源,有太多的併發請求也可能引發失效,例如不能分配 JDBC 鏈接。

      • 併發錯誤

        線程池和其它排隊機制依靠使用 wait() 和 notify() 方法,這兩個方法都難於使用。若是編碼不正確,那麼可能丟失通知,致使線程保持空閒狀態,儘管隊列中有工做要處理。使用這些方法時,必須格外當心;即使是專家也可能在它們上面出錯。而最好使用現有的、已經知道能工做的實現,例如 util.concurrent 包。

      • 線程泄漏

        各類類型的線程池中一個嚴重的風險是線程泄漏,當從池中除去一個線程以執行一項任務,而在任務完成後該線程卻沒有返回池時,會發生這種狀況。發生線程泄漏的一種情形出如今任務拋出一個 RuntimeException 或一個 Error 時。若是池類沒有捕捉到它們,那麼線程只會退出而線程池的大小將會永久減小一個。當這種狀況發生的次數足夠多時,線程池最終就爲空,並且系統將中止,由於沒有可用的線程來處理任務。

        有些任務可能會永遠等待某些資源或來自用戶的輸入,而這些資源又不能保證變得可用,用戶可能也已經回家了,諸如此類的任務會永久中止,而這些中止的任務也會引發和線程泄漏一樣的問題。若是某個線程被這樣一個任務永久地消耗着,那麼它實際上就被從池除去了。對於這樣的任務,應該要麼只給予它們本身的線程,要麼只讓它們等待有限的時間。

      • 請求過載

        僅僅是請求就壓垮了服務器,這種狀況是可能的。在這種情形下,咱們可能不想將每一個到來的請求都排隊到咱們的工做隊列,由於排在隊列中等待執行的任務可能會消耗太多的系統資源並引發資源缺少。在這種情形下決定如何作取決於您本身;在某些狀況下,您能夠簡單地拋棄請求,依靠更高級別的協議稍後重試請求,您也能夠用一個指出服務器暫時很忙的響應來拒絕請求。

Android的數據存儲形式

Shared PreferencesStore private primitive data in key-value pairs.

Internal StorageStore private data on the device memory.

External StorageStore public data on the shared external storage.

SQLite DatabasesStore structured data in a private database.

Network ConnectionStore data on the web with your own network server.

Content Provider不能算是一種數據存儲方式。它只是給咱們提供操做數據的接口,Content Provider背後其實仍是SQLite、File I\O等其餘方式

MVC for Android

MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯彙集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。
其中M層處理數據,業務邏輯等;V層處理界面的顯示結果;C層起到橋樑的做用,來控制V層和M層通訊以此來達到分離視圖顯示和業務邏輯層。

1.M層:適合作一些業務邏輯處理,好比數據庫存取操做,網絡操做,複雜的算法,耗時的任務等都在model層處理。
2.V層:應用層中處理數據顯示的部分,XML佈局能夠視爲V層,顯示Model層的數據結果。
3.C層:在Android中,Activity處理用戶交互問題,所以能夠認爲Activity是控制器,Activity讀取V視圖層的數據(eg.讀取當前EditText控件的數據),控制用戶輸入(eg.EditText控件數據的輸入),並向Model發送數據請求(eg.發起網絡請求等)。

Android抽象佈局——include、merge 、ViewStub

<include />標籤可以重用佈局文件
      • <include />標籤可使用單獨的layout屬性,這個也是必須使用的。
      • 可使用其餘屬性。<include />標籤若指定了ID屬性,而你的layout也定義了ID,則你的layout的ID會被覆蓋,解決方案。
      • 在include標籤中全部的android:layout_*都是有效的,前提是必需要寫layout_width和layout_height兩個屬性。
減小視圖層級<merge />

標籤在UI的結構優化中起着很是重要的做用,它能夠刪減多餘的層級,優化UI。<merge/>多用於替換FrameLayout或者當一個佈局包含另外一個時,<merge/>標籤消除視圖層次結構中多餘的視圖組。例如你的主佈局文件是垂直佈局,引入了一個垂直佈局的include,這是若是include佈局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI表現。這時可使用<merge/>標籤優化。

須要時使用<ViewStub />

<ViewStub />標籤最大的優勢是當你須要時纔會加載,使用他並不會影響UI初始化時的性能。各類不經常使用的佈局想進度條、顯示錯誤消息等可使用<ViewStub />標籤,以減小內存使用量,加快渲染速度。<ViewStub />是一個不可見的,大小爲0的View。<ViewStub />標籤使用以下:

<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />

當你想加載佈局時,可使用下面其中一種方法:

((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();

當調用inflate()函數的時候,ViewStub被引用的資源替代,而且返回引用的view。 這樣程序能夠直接獲得引用的view而不用再次調用函數findViewById()來查找了。
注:ViewStub目前有個缺陷就是還不支持 標籤。

Json有什麼優劣勢

優勢:

      1. 數據格式比較簡單,易於讀寫,格式都是壓縮的,佔用帶寬小,瀏覽器解析快
      2. 易於解析這種語言,客戶端JavaScript能夠簡單的經過eval()進行JSON數據的讀取
      3. 構造友好,支持多種語言,包括ActionScript, C,C#,ColdFusion,Java,JavaScript,Per,PHP,Python,Ruby等語言服務器端語言,便於服務器端的解析
      4. 在PHP世界,已經有PHP-JSON和JSON-PHP出現了,便於PHP序列化後的程序直接調用,PHP服務器端的對象、數組等可以直接生JSON格式,便於客戶端的訪問提取
      5. 由於JSON格式可以直接爲服務器端代碼使用,大大簡化了服務器端和客戶端的代碼開發量, 可是完成的任務不變, 且易於維護
        6.至關穩定。JSON 的附加內容將成爲超集

缺點:

      1. 沒有XML格式這麼推廣的深刻人心和使用普遍,沒有XML那麼通用性
      2. JSON格式目前在Web Service中推廣還屬於初級階段

Asset目錄與res目錄的區別

1.assets:不會在R.java文件下生成相應的標記,存放到這裏的資源在運行打包的時候都會打入程序安裝包中

2.res:會在R.java文件下生成標記,這裏的資源會在運行打包操做的時候判斷哪些被使用到了,沒有被使用到的文件資源是不會打包到安裝包中的。

在res文件夾下其實還能夠定義一下目錄:

res/anim:這裏存放的是動畫資源。

res/xml:能夠在Activity中使用getResource().getXML()讀取這裏的資源文件

res/raw:該目錄下的文件能夠直接複製到設備上,編譯軟件時,這裏的數據不須要編譯,直接加入到程序安裝包中,使用方法是getResource().OpenRawResources(ID),其中參數ID的形式是R.raw.XXX.

顯示Intent和隱式Intent區別

對明確指出了目標組件名稱的Intent,咱們稱之爲「顯式Intent」。
對於沒有明確指出目標組件名稱的Intent,則稱之爲「隱式 Intent」。
對於隱式意圖,在定義Activity時,指定一個intent-filter,當一個隱式意圖對象被一個意圖過濾器進行匹配時,將有三個方面會被參考到:

動做(Action)
類別(Category [‘kætɪg(ə)rɪ] )
數據(Data )

什麼是線程池,線程池的做用是什麼

線程池的基本思想仍是一種對象池的思想,開闢一塊內存空間,裏面存放了衆多(未死亡)的線程,池中線程執行調度由池管理器來處理。當有線程任務時,從池中取一個,執行完成後線程對象歸池,這樣能夠避免反覆建立線程對象所帶來的性能開銷,節省了系統的資源。就比如原來去食堂打飯是每一個人看誰搶的贏,誰先搶到誰先吃,有了線程吃以後,就是排好隊形,今天我跟你關係好,你先來吃飯。好比:一個應用要和網絡打交道,有不少步驟須要訪問網絡,爲了避免阻塞主線程,每一個步驟都建立個線程,在線程中和網絡交互,用線程池就變的簡單,線程池是對線程的一種封裝,讓線程用起來更加簡便,只須要創一個線程池,把這些步驟像任務同樣放進線程池,在程序銷燬時只要調用線程池的銷燬函數便可。
單個線程的弊端:a. 每次new Thread新建對象性能差b. 線程缺少統一管理,可能無限制新建線程,相互之間競爭,及可能佔用過多系統資源致使死機或者OOM,c. 缺少更多功能,如定時執行、按期執行、線程中斷。
java提供的四種線程池的好處在於:a. 重用存在的線程,減小對象建立、消亡的開銷,性能佳。b. 可有效控制最大併發線程數,提升系統資源的使用率,同時避免過多資源競爭,避免堵塞。c. 提供定時執行、按期執行、單線程、併發數控制等功能。

Java 線程池

Java經過Executors提供四種線程池,分別爲:

newCachedThreadPool建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。

newFixedThreadPool 建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支持定時及週期性任務執行。

newSingleThreadExecutor 建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行。

(1). newCachedThreadPool
建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。線程池爲無限大,當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的線程,而不用每次新建線程。

(2). newFixedThreadPool
建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。

(3) newScheduledThreadPool
建立一個定長線程池,支持定時及週期性任務執行。ScheduledExecutorService比Timer更安全,功能更強大

(4)、newSingleThreadExecutor
建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行

IntentService的用法

1、IntentService簡介

IntentService是Service的子類,比普通的Service增長了額外的功能。先看Service自己存在兩個問題:

Service不會專門啓動一條單獨的進程,Service與它所在應用位於同一個進程中;

Service也不是專門一條新線程,所以不該該在Service中直接處理耗時的任務;

2、IntentService特徵

會建立獨立的worker線程來處理全部的Intent請求;

會建立獨立的worker線程來處理onHandleIntent()方法實現的代碼,無需處理多線程問題;

全部請求處理完成後,IntentService會自動中止,無需調用stopSelf()方法中止Service;

爲Service的onBind()提供默認實現,返回null;

爲Service的onStartCommand提供默認實現,將請求Intent添加到隊列中;

IntentService不會阻塞UI線程,而普通Serveice會致使ANR異常
Intentservice若未執行完成上一次的任務,將不會新開一個線程,是等待以前的任務完成後,再執行新的任務,等任務完成後再次調用stopSelf

Handler的實現原理

handler幹了些什麼:

運行在某個線程上,共享線程的消息隊列;

接收消息、調度消息,派發消息和處理消息;

實現消息的異步處理;

創建消息處理模型/系統

參考博客

Context與ApplicationContext的區別,分別用在什麼狀況下

Application的Context是一個全局靜態變量,SDK的說明是隻有當你引用這個context的生命週期超過了當前activity的生命週期,而和整個應用的生命週期掛鉤時,纔去使用這個application的context。

在android中context能夠做不少操做,可是最主要的功能是加載和訪問資源。在android中有兩種context,一種是 application context,一種是activity context,一般咱們在各類類和方法間傳遞的是activity context。

View的繪製流程

1.onmesarue() 爲整個View樹計算實際的大小

2.onlayout() 爲將整個根據子視圖的大小以及佈局參數將View樹放到合適的位置上

3.ondraw()

1 、繪製該View的背景
2 、爲顯示漸變框作一些準備操做(見5,大多數狀況下,不須要改漸變框)
三、調用onDraw()方法繪製視圖自己 (每一個View都須要重載該方法,ViewGroup不須要實現該方法)
四、調用dispatchDraw ()方法繪製子視圖(若是該View類型不爲ViewGroup,即不包含子視圖,不須要重載該方法)

觸摸屏幕的分發機制

一、基礎知識

(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

二、傳遞流程

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被中止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View能夠經過onTouchEvent()對事件進行處理。

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup能夠經過onInterceptTouchEvent()對事件作攔截,中止其往下傳遞。

(3) 若是事件從上往下傳遞過程當中一直沒有被中止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)能夠進行消費,若是仍是沒有被消費的話,最後會到Activity的onTouchEvent()函數。

(4) 若是View沒有對ACTION_DOWN進行消費,以後的其餘事件不會傳遞過來。

(5) OnTouchListener優先於onTouchEvent()對事件進行消費。

相關文章
相關標籤/搜索