LoaderManager與CursorLoader用法

来源:http://www.cnblogs.com/ganchuanpu/archive/2017/04/20/6741280.html
-Advertisement-
Play Games

一.基本概念 1.LoaderManager LoaderManager用來負責管理與Activity或者Fragment聯繫起來的一個或多個Loaders對象. 每個Activity或者Fragment都有唯一的一個LoaderManager實例(通過getLoaderManager()方法獲得) ...


一.基本概念

1.LoaderManager
 LoaderManager用來負責管理與Activity或者Fragment聯繫起來的一個或多個Loaders對象.
 每個Activity或者Fragment都有唯一的一個LoaderManager實例(通過getLoaderManager()方法獲得),用來啟動,停止,保持,重啟,關閉它的Loaders,這些功能可通過調用initLoader()/restartLoader()/destroyLoader()方法來實現.
 LoaderManager並不知道數據如何裝載以及何時需要裝載.相反,它只需要控制它的Loaders們開始,停止,重置他們的Load行為,在配置變換或數據變化時保持loaders們的狀態,並使用介面來返回load的結果.

 2.Loader
 Loades負責在一個單獨線程中執行查詢,監控數據源改變,當探測到改變時將查詢到的結果集發送到註冊的監聽器上.Loader是一個強大的工具,具有如下特點
 (1)它封裝了實際的數據載入.
 Activity或Fragment不再需要知道如何載入數據.它們將該任務委托給了Loader,Loader在後臺執行查詢要求並且將結果返回給Activity或Fragment.
 (2)客戶端不需要知道查詢如何執行.Activity或Fragment不需要擔心查詢如何在獨立的線程中執行,Loder會自動執行這些查詢操作.
 這種方式不僅減少了代碼複雜度同事也消除了線程相關bug的潛在可能.
 (3)它是一種安全的事件驅動方式.
 Loader檢測底層數據,當檢測到改變時,自動執行並載入最新數據.
 這使得使用Loader變得容易,客戶端可以相信Loader將會自己自動更新它的數據.
 Activity或Fragment所需要做的就是初始化Loader,並且對任何反饋回來的數據進行響應.除此之外,所有其他的事情都由Loader來解決.

二.非同步Loader的實現原理 

(1)執行非同步載入的任務.為了確保在一個獨立線程中執行載入操作,Loader的子類必須繼承AsyncTaskLoader<D>而不是Loader<D>類.
 AsyncTaskLoader<D>是一個抽象Loader,它提供了一個AsyncTask來做它的執行操作.
 當定義子類時,通過實現抽象方法loadInBackground方法來實現非同步task.該方法將在一個工作線程中執行數據載入操作.
 (2)在一個註冊監聽器中接收載入完成返回的結果.
 對於每個Loader來說,LoaderManager註冊一個OnLoadCompleteListener<D>,該對象將通過調用onLoadFinished(Loader<D> loader, D result)方法使Loader將結果傳送給客戶端.
 Loader通過調用Loader#deliverResult(D result),將結果傳遞給已註冊的監聽器.

三.Loader三種不同狀態. 

已啟動: 處於已啟動狀態的Loader會執行載入操作,併在任何時間將結果傳遞到監聽器中.已啟動的Loader將會監聽數據改變,當檢測到改變時執行新的載入. 一旦啟動,Loader將一直                    處在已啟動狀態,一直到轉換到已停止和重置,這是唯一一種onLoadFinished永遠都會調用的狀態。
已停止: 處於已停止狀態的Loader將會繼續監聽數據改變,但是不會將結果返回給客戶端.在已停止狀態,Loader可能被啟動或者重啟.
重置:   當Loader處於重置狀態時,將不會執行新的載入操作,也不會發送新的結果,也不會檢測數據變化.
       當一個Loader進入重置狀態,它必須解除對應的數據引用,方便垃圾回收(客戶端也必須確定,在Loader無效之後,移除了所有對該數據的引用).
      通常,重置Loader不會兩次調用.然而,在某些情況下他們可能會啟動,所以如果必要的話,它們必須能夠適時重置.

四.接收Loader數據改變的通知. 

必須有一個觀察者接受數據源改變的通知.
 Loader必須實現這些Observer其中之一(ContentObserver,BroadcastReceiver等),來檢測底層數據源的改變.
 當檢測到數據改變,觀察者必須調用Loader#onContentChanged().在該方法中執行兩種不同操作:
 (1)如果Loader已經處於啟動狀態,就會執行一個新的載入操作;

 (2)設置一個flag標識數據源有改變,這樣當Loader再次啟動時,就知道應該重新載入數據了. 

五.CursorLoader實現LoaderManager.LoaderCallbacks介面方法.介面聲明及使用如下: 

public interface LoaderCallbacks<D> {
  public Loader<D> onCreateLoader(int id, Bundle args);
  public void onLoadFinished(Loader<D> loader, D data);
  public void onLoaderReset(Loader<D> loader);
 }
 
 onCreateLoader方法將在創建Loader時候調用,此時需要提供查詢的配置,如監聽一個URI.
 這個方法會在loader初始化的時調用,即調用下麵的代碼時調用:
  getLoaderManager().initLoader(id, bundle, loaderCallbacks);
  initLoader函數原型為:
  <D> Loader<D> android.app.LoaderManager.initLoader(int id, Bundle bundle, LoaderCallbacks<D> loaderCallbacks);
  第1個參數loader的ID,可自定義一個常量值,便於實現多個Loader;
  第2個參數一般置null;
  第3個參數是實現了LoaderManager.LoaderCallbacks實現類對象.
 onLoadFinished方法,在Loader完成任務後調用,一般在此讀取結果.
 onLoaderReset方法是在配置發生變化時調用,一般調用下麵的代碼後調用:
  getLoaderManager().restartLoader(id, bundle, loaderCallbacks);
  restartLoader方法參數同initLoader,重新初始化loader之後,需要用來釋放對前面loader查詢到的結果引用.  

六.一個具體監聽通話記錄的示例 

在Activity中onCreate調用 

 CallLogsLoaderListener callLogsCallback = new CallLogsLoaderListener(this);
  getLoaderManager().initLoader(0, null, callLogsCallback);
 
 在onDestroy調用
  getLoaderManager().destroyLoader(0);
 
 配置許可權
  <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
  <uses-permission android:name="android.permission.READ_CALL_LOG" />
 
 具體的類實現

import android.app.LoaderManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.os.Bundle;
import android.provider.CallLog;
import android.util.Log;

public class CallLogsLoaderListener implements
        LoaderManager.LoaderCallbacks<Cursor> {

    private Context mContext;

    public CallLogsLoaderListener(Context context) {
        mContext = context;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        CursorLoader loader = new CursorLoader(mContext,
                CallLog.Calls.CONTENT_URI, null, null, null, null) {
            @Override
            public Cursor loadInBackground() {
                Cursor cursor = super.loadInBackground();
                if (cursor == null)
                    return null;
                CallLogsCursor callLogsCursor = new CallLogsCursor(cursor);
                return callLogsCursor;
            }
        };
        return loader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    public class CallLogsCursor extends CursorWrapper {

        public CallLogsCursor(Cursor cursor) {
            super(cursor);

            int nameIndex = cursor.getColumnIndex(CallLog.Calls.CACHED_NAME);
            int numberIndex = cursor.getColumnIndex(CallLog.Calls.NUMBER);
            int typeIndex = cursor.getColumnIndex(CallLog.Calls.TYPE);
            int dateIndex = cursor.getColumnIndex(CallLog.Calls.DATE);
            int durationIndex = cursor.getColumnIndex(CallLog.Calls.DURATION);

            // 從游標的最後索引往前查詢,因為最新的通話記錄在最後
            for (cursor.moveToLast(); !cursor.isBeforeFirst(); cursor
                    .moveToPrevious()) {
                // 姓名
                String name = cursor.getString(nameIndex);
                // 號碼
                String number = cursor.getString(numberIndex);
                // 類型
                int type = cursor.getInt(typeIndex);
                // 日期
                long date = cursor.getLong(dateIndex);
                // 通話時長
                int duration = cursor.getInt(durationIndex);

                Log.d("debug", "name=" + name + ", number=" + number
                        + ", type=" + type + ", date=" + date + ", duration="
                        + duration);
            }
        }
    }
}

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關於三個構造函數使用時機的說法 也就是說,系統預設只會調用Custom View的前兩個構造函數,至於第三個構造函數的調用,通常是我們自己在構造函數中主動調用的(例如,在第二個構造函數中調用第三個構造函數). ...
  • Activity代碼 自定義view 看下自定義view 類,主要onDraw()方法中. 繪製中分為三部分, 第一部分為上部分半透明區域 第二部分為下部分全透明區域 第三部分就是中間的progress值變化 ...
  • 一.對android:configChanges屬性,一般認為有以下幾點:1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次2、設置Activity的android:configChanges="orienta ...
  • ex : Precondition : R_CHARGER_1 是 int type R_CHARGER_2 是 int type val 是 int type val = (((R_CHARGER_1+R_CHARGER_2) 100 val)/R_CHARGER_2)/100; 為什麼要乘100 ...
  • 基於Android 7.0源碼,深入解析init進程及main函數的邏輯功能 ...
  • ReactJS 是否準備好 有時候我們常常需要監聽 ReactJS 的的載入情況。 比如說,當獲取一條推送,應用還沒有起來,通過點擊推送啟動應用後,而推送中包含一些我們感興趣的欄位需要處理,我們如果直接把這條通知發送給 ReactJS,會有一個問題,就是應用是剛啟動的,ReactJS 還沒有成功載入 ...
  • 微信 小程式開始火了,app跨平臺的革命再次高漲,不得不說,不用再擔心android和ios雙版本開發成本,及h5的開發 和apicloud一樣,不需要關註平臺問題,只需要關註前端js、css就能大aodroin和ios上完美相容,贊贊贊~ 那麼apicloud 和 微信小程式又有什麼區別和共通呢? ...
  • 1.裝載器API概述 Class/Interface 說明 LoaderManager 一個抽像類,關聯到一個Activity或Fragment,管理一個或多個裝載器的實例。這幫助一個應用管理那些與Activity或Fragment的生命周期相關的長時間運行的的操作。最常見的方式是與一個Cursor ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...