【Android】19.3 ContentProvider及安卓進一步封裝後的相關類

来源:http://www.cnblogs.com/rainmj/archive/2016/03/08/5252600.html
-Advertisement-
Play Games

分類:C#、Android、VS2015; 創建日期:2016-03-08 一、簡介 ContentProvider:內容提供程式。 Android的ContentProvider與.NET框架的EF(Entity Framework)非常類似。在EF中,每個類表示資料庫中的一個表,類中的每個屬性對...


分類:C#、Android、VS2015;

創建日期:2016-03-08

一、簡介

ContentProvider:內容提供程式。

Android的ContentProvider與.NET框架的EF(Entity Framework)非常類似。在EF中,每個類表示資料庫中的一個表,類中的每個屬性對應表的欄位,類的每個實例表示資料庫表的一行記錄。同樣,在Android中,每個ContentProvider類的實例表示數據表的一行記錄,ContentProvider實例集合中的每一項表示數據表中的一列。

另外,Entity Framework的數據源不一定是資料庫,也可以是其他類型的數據。同樣,Android的ContentProvider可訪問的數據源也不一定是資料庫,也一樣可以是其他類型的數據。而且EF和ContentProvider也都提供了對數據源的CRUD(Create、Read、Update、Delete)操作。

可將ContentProvider理解為在不同的進程之間實現數據交互或數據共用的工具。換言之,利用ContentProviders,可訪問由其他應用程式公開的數據,比如訪問Android的系統數據(如聯繫人、媒體和日曆信息)、SQLite資料庫、文件等。

1、安卓內置的內容提供程式(Built-In Providers)

安卓內置的所有Provide都在Android.Provider命名空間下,這些類有:

  • Android.Provider.Browser類–瀏覽書簽的歷史記錄(此操作需要READ_HISTORY_BOOKMARKS或WRITE_HISTORY_BOOKMARKS許可權)。
  • Android.Provider.CallLog類 –通話記錄。查看最近撥出或收到的電話。
  • Android.Provider.ContactsContract類 –聯繫人。查看用戶的聯繫人名單,包括姓名、電話、照片等信息。
  • Android.Provider.MediaStore類 –媒體存儲。查看設備上用戶存儲的媒體文件,包括音頻、圖像、視頻等。
  • Android.Provider.Settings類 –系統設置和首選項。
  • Android.Provider.UserDictionary類 –用於預測文本輸入的用戶定義的字典。
  • Android.Provider.VoicemailContract類 –語音信箱中的聯繫人及其歷史記錄。

安卓內置的所有Provide實際上都是通過ContentProvider來操作的,只是它封裝以後你看不到ContentProvider了,換言之,你直接使用它對ContentProvider進一步封裝後的這些類就行了,這樣用起來更方便些。

2、如何使用這些內置的提供程式

使用ContentProvider的首選方式是利用LoaderManager中的CursorLoader類得到ContentProvider的實例。,這種方式實際上是通過先關閉主線程然後再利用數據綁定來載入數據的。得到ContentProviders的實例以後,就可以通過CursorAdapters將ContentProviders載入的數據顯示出來。

前面剛剛說過,由於Android對ContentProvider做了進一步的封裝,因此在代碼中訪問Android系統通過ContentProvider公開的數據時,它實際是使用ContentProvider類來處理它的,只是你看不到它是這樣做的而已。換言之,對於開發人員來說,它對其封裝以後,要求你先通過Uri創建一個游標(cursor),然後再利用這個cursor對象訪問它公開的數據。

下麵以android.provider.ContactsContract類為例說明Uri的含義和用法,Built-In Providers中其他類的用法與此相似。

Uri實際上就是把DNS顛倒過來寫的一個字元串,例如:

com.android.contacts/data

為了不讓開發人員耗費精力去理解和記住這個原始字元串,Android的Contacts(聯繫人)提供程式在android.provider.ContactsContract類中又以常量的形式公開了這些元數據,你只需要通過這些常量,即可得到ContentProvider的Uri、可查詢的表名以及列名。

有3種通過Uri創建游標(cursor)的方式:

  • CursorLoader().LoadInBackground() –這是首選方式,是從Android 3.0 (API Level 11)開始引入的處理辦法。由於CursorLoader是通過後臺線程查詢ContentResolver的,因此該方法不會引起界面阻塞,而且不用時還能自動關閉它。另外,如果你希望在比Android 3.0更低的版本中使用這個類,可通過v4相容庫(v4 compatibility library)來訪問。
  • ContentResolver.Query() –使用這種辦法得到cursor對象後,不用時必須調用cursor.Close()關閉它,否則就會引起記憶體泄漏。
  • ManagedQuery() –這是Android 2.3 (API Level 10) 及更早版本中提供的方法。註意該方法在 Android 3.0 (API 級別 11) 中就已經被標記為已過時,因此不要再使用它。

在Android公開的這些方法中,不論使用哪種方式,都需要提供以下幾個基本參數:

  • Uri –內容的完全限定名稱。
  • Projection – 投影。其作用是為cursor指定選擇的一列或多列。
  • Selection – 其作用類似於SQL的WHERE子句。
  • SelectionArgs – 用參數替換WHERE子句中所選的內容。
  • SortOrder – 指定排序的列。

再次強調一下,CursorLoader是使用ContentProvider的首選方式。

3、自定義ContentProvider

除了上面介紹的Android內置的Provider外,你還可以創建自定義的Provider。資料庫一章中已經介紹過其用法了,這裡不再重覆。

二、例19-3—用CursorLoader讀取和更新通訊錄

這一節仍以讀取和更新通訊錄為例,演示CursorLoader的基本用法。該例子是在【12.5利用Intent讀取和更新通訊錄】例子的基礎上改進的,在這個該例子中,除了像例12-4那樣顯示出聯繫人外,如果通訊錄中你輸入了聯繫人的照片,還能把對應的照片顯示出來。如果你沒有在通訊錄中輸入照片,就用預設的照片來代替。

1、運行截圖

由於是例子,所以截圖中的通訊錄照片是隨便選的一個圖。

image

2、設計步驟

(1)該例子需要的許可權

由於前面章節的例子已經添加過這些許可權,所以不需要再添加了。如果你單獨創建一個項目,必須添加下麵的許可權。

<uses-permission android:name="android.permission.WRITE_PROFILE" />

<uses-permission android:name="android.permission.READ_PROFILE" />

<uses-permission android:name="android.permission.READ_CONTACTS" />

<uses-permission android:name="android.permission.WRITE_CONTACTS" />

(2)添加ch1903_contact_picture.png

在drawable文件夾下添加該文件。用於找不到聯繫人照片時顯示的替換照片。

(3)添加ch1903ContactListItem.xml

在layout文件夾下添加該文件。

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
  <ImageView
      android:id="@+id/ch1903_ContactImage"
      android:layout_width="50dp"
      android:layout_height="50dp"
      android:layout_margin="5dp" />
  <TextView
      android:id="@+id/ch1903_ContactName"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:layout_marginLeft="5dp" />
</LinearLayout>

(4)添加ch1903Main.axml

在layout文件夾下添加該文件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView
        android:id="@+id/ch1903_ContactsListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

(5)添加ch1903MainActivity.cs

在SrcDemos文件夾下添加該文件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Provider;
using Android.Database;

namespace MyDemos.SrcDemos
{
    [IntentFilter(new[] { Intent.ActionMain }, Categories = new[] { ch.MyDemosCategory })]
    [Activity(Label = "【例19-3】ContentProvider基本用法")]
    public class ch1903MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.ch1903Main);
            var contactsAdapter = new ContactsAdapter(this);
            var contactsListView = FindViewById<ListView>(Resource.Id.ch1903_ContactsListView);
            contactsListView.Adapter = contactsAdapter;
        }
    }

    public class ContactsAdapter : BaseAdapter<ch1903Contact>
    {
        List<ch1903Contact> contactList;
        Activity activity;

        public override int Count
        {
            get { return contactList.Count; }
        }

        public override ch1903Contact this[int position]
        {
            get { return contactList[position]; }
        }

        public ContactsAdapter(Activity activity)
        {
            this.activity = activity;
            FillContacts();
        }

        public override long GetItemId(int position)
        {
            return contactList[position].Id;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            var view = convertView ?? activity.LayoutInflater.Inflate(Resource.Layout.ch1903ContactListItem, parent, false);
            var contactName = view.FindViewById<TextView>(Resource.Id.ch1903_ContactName);
            var contactImage = view.FindViewById<ImageView>(Resource.Id.ch1903_ContactImage);
            contactName.Text = contactList[position].DisplayName;
            if (contactList[position].PhotoId == null)
            {
                contactImage = view.FindViewById<ImageView>(Resource.Id.ch1903_ContactImage);
                contactImage.SetImageResource(Resource.Drawable.ch1903_contact_picture);
            }
            else
            {
                var contactUri = ContentUris.WithAppendedId(ContactsContract.Contacts.ContentUri, contactList[position].Id);
                var contactPhotoUri = Android.Net.Uri.WithAppendedPath(contactUri, ContactsContract.Contacts.Photo.ContentDirectory);
                contactImage.SetImageURI(contactPhotoUri);
            }
            return view;
        }

        private void FillContacts()
        {
            var uri = ContactsContract.Contacts.ContentUri;
            string[] projection = {
                    ContactsContract.Contacts.InterfaceConsts.Id,
                    ContactsContract.Contacts.InterfaceConsts.DisplayName,
                    ContactsContract.Contacts.InterfaceConsts.PhotoId
                };

            // 下麵這條語句已過時,不要使用它
            //var cursor = activity.ManagedQuery (uri, projection, null, null, null);

            // 如果用下麵這條語句,不用時必須調用cursor.Close()關閉它
            //var cursor = activity.ContentResolver.Query(uri, projection, null, null, null);

            // 下麵是建議的用法
            var loader = new CursorLoader(activity, uri, projection, null, null, null);
            var cursor = (ICursor)loader.LoadInBackground();
            contactList = new List<ch1903Contact>();
            if (cursor.MoveToFirst())
            {
                do
                {
                    contactList.Add(new ch1903Contact
                    {
                        Id = cursor.GetLong(cursor.GetColumnIndex(projection[0])),
                        DisplayName = cursor.GetString(cursor.GetColumnIndex(projection[1])),
                        PhotoId = cursor.GetString(cursor.GetColumnIndex(projection[2]))
                    });
                } while (cursor.MoveToNext());
            }
        }
    }

    public class ch1903Contact
    {
        public long Id { get; set; }
        public string DisplayName { get; set; }
        public string PhotoId { get; set; }
    }
}

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

-Advertisement-
Play Games
更多相關文章
  • 原文出處: 攜程設計委員會 現在手機的占比越來越高,各種酷炫頁面層出不窮,這些特效都離不開css動畫。說到css動畫,主流的情況也就無非這兩大類:位移和形變。而我們在寫一個動畫特效的過程中,如何去提升它的性能呢?當然首先我們需要去瞭解一下基本的概念,比如瀏覽器渲染的工作原理等,這些我也在讀了幾位大牛
  • 看到這樣一個問題:為什麼直接在控制台運行{} + []和用console.log({} + [])輸出,兩者結果不一樣? 於是乎打開chrome的控制台運行了一下: 為什麼結果會這樣呢?不得已學習一下JS中的{}吧 複合語句 1 if() { 2 //... 3 }else { 4 //... 5
  • 除了慣例的面對對象的思想,另一種較流行的通過可復用組件創建類的方法是將簡單的類混合到一起。你可能對這種混合的方式比較熟悉或對Scala語言的特性有理解,這種模式在JavaScript社區也有一定的人氣。 混合案例 在下麵的代碼中,我們展示瞭如何在TypeScript中混合模型,看完代碼之後,再分析它
  • 關於JavaScipt對象的基本知識 JavaScript是運用“對象化編程”的,又叫“面向對象編程”的。所謂“對象化編程”,意義是把JavaScript能涉及的領域劃分成各種對象,對象後面還連續劃分對象直至很是詳細為止,整個的編程都以對象為出發點,基於對象。何謂對象,小到一個變數,大到網頁文檔、窗
  • 一個成熟的框架,日期控制是少不了的,在網上也有很多日期控制可以選擇,而主框架用了bootstrap,日期控制也當前要用它自己的, 控制項地址:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm GitHub上開源地址:https://
  • 有一個功能需要判斷返回頂部按鈕是否顯示。 JS代碼如下: var sTop = document.body.scrollTop; if(sTop>100){ document.getElementById("sm_top").style.display="block"; }else{ documen
  • 1.內置對象創建 var girl=new Object(); girl.name='hxl'; console.log(typeof girl); 2.工廠模式,寄生構造函數模式 function Person(name){ var p=new Object();//內部進行實例化 p.name=
  • package com.example.yanlei.myyk; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; im
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...