【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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...