Android 四大組件相關知識點

Activity

1.當指定的Activity在用戶可見後才進行廣播註冊,在用戶不可見後對廣播進行註銷,那麼應該在哪兩個回調中做這個處理?

可見——onStart();

不可見——onStop();

2.如果有一些數據在Activity跳轉(或者離開時)要保存到數據庫中,在onPause()中執行比較好;

理由:onPause()方法是進程被殺死之前保證會執行的最後一個方法,簡單來說,在執行了onPause()方法之後,直到執 行onResume()之前,該activity所在的進程都是有可能“突然死亡”的,onStop()和onDestroy()方法並不能保證一定會被執行。所以onPause()方法是持久化相關數據的最後的可靠時機。

3.ActivityA啓動ActivityB,它們的生命週期變化:

ActivityA:onCreate()---onStart()---onResume()---啓動ActivityB---onPause()---onStop()

ActivityB: onCreate()---onStart()---onResume()---Back---onPause()---ActivityA重新啓動---onStop()---onDestory()

ActivityA: onRestart()---onStart()---onResume()---Back---onPause()---onStop()---onDestory()

注:如果內存不夠,A可能執行onDestory(),建議在savedInstanceState中保存關鍵數據

4.ActivityA 通過intent顯示啓動了ActivityB ,當B處於可見時,A是否一定調用onStop()?

不一定,若B是dialog(對話框),當B處於可見時,A也可見(但不能與用戶交互,處於onPause()),不會調用onStop() .

5.不是所有的數據存儲要放在onPause()

當要執行比較耗時 的操作時,不要在onPause()中執行,因爲會影響下一個活動的顯示,onPause()不執行完,下一個活動的onResume()無法執行,無法正常顯示。Service

開啓服務有兩種方式: StartService() BindService().

starService 開啓一個服務,會執行onCreate()方法,和onStart()方法,如果服務已經開啓,只會執行onStart()方法。

服務開啓後,就會在後臺長期運行,可以在設置界面找到,我們可以在設置界面手動關閉它,服務就會停止運行。

startService開啓服務也叫做非綁定模式開啓服務 ,生命週期 第一次執行的方法有 onCreate().onstartCommand(),到service關閉的時候執行onDestroy()方法。

bindService開啓服務也叫做綁定模式開啓服務,生命週期 第一次執行的方法有 onCreate(), onBind()方法,

銷燬的時候執行onUnBind(),onDestroy()方法, bindService開啓服務有個特點,它在設置界面時找不到的,所以我們無法手動在設置界面銷燬它,不過它的生命週期依附於Activity,當Activity銷燬的時候,這個服務也就跟着銷燬。

上面兩種生命週期實在相對單純的模式下的情形,我們在開發的過程中還必須注意Service實例只會有一個,也就是說如果當前要啓動的Service已經存在了那麼就不會再次創建該Service當然也不會調用onCreate()方法;

一個Service可以被多個客戶進行綁定,只有所有綁定對象都執行了onBind()方法後該Service纔會銷燬,不過如果有一個用戶執行了onStart()方法,那麼這個時候如果其他所有的bind客戶都執行了unBind()。該Service也不會銷燬,很多應用都是用startService和bindService混合開啓服務,比如音樂播放器,第三方支付等

在前臺運行服務

我們之前定義的服務都是運行在後臺的,這樣的服務當系統內存不足時將會被殺死,而用戶卻毫不知情。如果想要一個服務的狀態可以被用戶一眼看到,那麼可以使用前臺服務。

將一個服務設置爲前臺服務,只需要在綁定時調用startForeground將自己設置爲前臺服務即可,其中第二個參數是Notification對象,表示在通知欄中顯示的通知。

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate: ");
    Intent intent = new Intent(this,MainActivity.class);
    PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
    Notification notification = new NotificationCompat.Builder(this)
            .setContentTitle("this is content title")
            .setContentText("this is content text")
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.mipmap.ic_launcher)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
            .setContentIntent(pi)
            .build();
    /**
     * 參數一:通知id,參數二:通知的對象
     */
    startForeground(1,notification);
}

服務是運行在主線程中,故不能執行耗時操作,具體實現是在服務具體方法內開啓一個子線程去執行,而且如果想要實現讓服務在執行完畢後自動停止的功能,需要調用stopSelf()方法。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand: ");
    //在服務具體方法中開啓線程執行耗時操作
    new Thread(new Runnable() {
        @Override
        public void run() {
            //具體邏輯
            //實現讓服務執行完畢後自動停止
            stopSelf();
        }
    }).start();
    return super.onStartCommand(intent, flags, startId);
}

而IntentService的出現實現了開啓線程自動停止的功能

IntentService

服務和Activity一樣,都是Android的組件,生命週期中的各個方法也都運行在主線程中。所以雖然服務名爲“服務”,但是如果想要其中執行耗時任務,還是需要將任務放入到線程中。IntentService就是這樣一種服務,Android已經爲我們封裝了創建線程的過程,只需要我們直接實現耗時任務的邏輯即可。IntentService的使用有如下限制

- 不可以直接和用戶交互。如果需要將結果與UI交互,需要將結果返回給Activity

- 工作請求遵循線性,FIFO

- IntentService中的操作不能被打斷

使用IntentService:

使用IntentService,只需要繼承自IntentService類,需要實現onHandleIntent方法,在這個方法中就可以編寫耗時任務。

public class MyIntentService extends IntentService {
    private static final String TAG = "MyIntentService";

    public MyIntentService() {
        super("MyIntentService");//調用父類有參構造函數
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "Thread id is " + Thread.currentThread().getId());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
}

BroadCastReceiver

廣播分兩種: 有序廣播和無序廣播

無序廣播:sendBroadcast()方法發送的廣播爲無序廣播,無序廣播邏輯上可以被任何廣播接受者接收到,優點是效率高。缺點是一個接收者不能將處理結果傳遞給下一個接收者,傳遞的數據在傳輸過程中不能被修改,並無法終止廣播的傳播。

有序廣播:sendOrderedBroadcast()方法發送的廣播爲有序廣播,有序廣播依次傳播,列如有三個廣播接收者A,B,C, 優先級是A>B>C, 此時發送一條廣播,那這個消息先傳給A,再傳給B, 最後傳給C,每個接收者都有權終止廣播,比如B終止廣播,C就無法接受到, 此外A接收到廣播後可以對結果對象進行操作,當廣播傳給B時,B可以從結果對象中獲取A存入的數據。

在通過context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,initialCode, initialData, initialExtras);時我們可以指定resultReceiver廣播接收者,這個接收者我們可以認爲是最終接收者,通常情況下如果比他優先級更高的接收者如果沒有終止廣播,那麼他的onReceive方法會被執行兩次,第一次是正常的按照優先級順序執行,第二次是作爲最終接收者接收,如果比他優先級高的接收者終止了廣播,那麼他依然能接收到廣播。

BroadcastReceiver有兩種註冊方法

在Androidmainfest中註冊廣播接收者稱爲靜態註冊

在代碼中註冊稱爲動態註冊

靜態註冊的廣播接收者只要app在系統中註冊則可以一直接收到廣播消息,

動態註冊的廣播接收者當註冊的activity或Service銷燬了那麼就接收不到廣播了

注意:

1.BroadcastReceiver的生命週期是非常短暫的,在接收廣播的時候創建,onReceiver()方法結束之後銷燬

2. 廣播接收者中不要做一些耗時的工作,否則會彈出Application No Response(應用無響應anr)錯誤對話框,,一般耗時的較長的操作最好放在服務中完成。

3.最好也不要在廣播接收者中創建子線程做耗時操作,因爲廣播接收者被銷燬後進程就成爲空進程,而空進程很容易被系統殺掉。

相關問題:

1.動態廣播註冊與銷燬在Activity那兩個生命週期進行?

onCreate()---onDestory();

2.靜態廣播與動態廣播的區別?特點和應用場景

生存期:靜態廣播的生存期可以比動態廣播的長很多,因爲靜態廣播很多都是用來對系統時間進行監聽,比如我們可以監聽手機開機。而動態廣播會隨着context的終止而終止

優先級:動態廣播的優先級比靜態廣播高

使用方式:動態廣播無需在AndroidManifest.xml中聲明即可直接使用,也即動態;而靜態廣播則需要,有時候還要在AndroidManifest.xml中加上一些權限的聲明

3.有時候基於數據安全考慮,我們想發送廣播只有自己(本進程)能接收到,怎麼處理?

使用本地廣播

4.Android 中用廣播來更新 UI 界面好嗎?

大多數情況下可以採用廣播來更新UI,但是不能太過耗時,還有頻繁更新UI,使用廣播是不推薦的。

5.BroadcastReceiver EventBus 有啥不同?

如果是和 Android 系統相關的通知,我們還得選擇本地廣播。廣播相對於其他實現方式,是很重量級的,它消耗的資源較多。它的優勢體現在和 SDK 的緊密聯繫,onReceive() 方法自帶了 Context 和 Intent 參數,所以在一定意義上實現了便捷性,但如果對 Context 和 Intent 應用很少或者說只做很少的交互的話,使用廣播真的就是一種浪費!!!

EventBus優點:

調度靈活,使用簡單,快速且輕量;

缺點:EventBus 最大的缺點在於其邏輯性

和Android的 BroadcastReceiver/Intent 不同,EventBus 用了標準java類的事件,提供了更方便的API。當你要用很多case去區分事件時,EventBus很一個很好的解決方案,你不需要大量設置intent、給intent添加extras、實現大量broadcast receivers、再獲得intent、從intent裏提取數據。而且,EventBus 的開銷低得多。

6.8.0之後廣播的變化

Android 8.0的平臺上,應用不能對大部分的廣播進行靜態註冊

ContextProvider

(1)android平臺提供了ContentProvider使一個應用程序的指定數據集提供給其他應用程序。其他應用可以通過ContentResolver類從該內容提供者中獲取或存入數據。

(2)只有需要在多個應用程序間共享數據是才需要內容提供者。例如,通訊錄數據被多個應用程序使用,且必須存儲在一個內容提供者中。它的好處是統一數據訪問方式。

(3)ContentProvider實現數據共享。ContentProvider用於保存和獲取數據,並使其對所有應用程序可見。這是不同應用程序間共享數據的唯一方式,因爲android沒有提供所有應用共同訪問的公共存儲區。

(4)開發人員不會直接使用ContentProvider類的對象,大多數是通過ContentResolver對象實現對ContentProvider的操作。

(5)ContentProvider使用URI來唯一標識其數據集,這裏的URI以content://作爲前綴,表示該數據由ContentProvider來管理。

重點理解和應用Content Provider API涉及到的相應參數:

利用這些參數和相應API完成數據的篩選。

/**

* @param uri 指定查詢應用程序下具體表

* @param projection 指定查詢的列名

* @param selection 指定where的約束條件

* @param selectionArgs 爲where中的佔位符提供具體的值

* @param sortOrder 指定查詢的排序方式

*/

@Override

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章