Android学习10Android上的数据存储02

来源:互联网 发布:java字符串补零 编辑:程序博客网 时间:2024/05/01 10:33

接上篇。

 

  5. Content Provider使用

             Content Provider属于Android应用程序的组件之一,在之前的文章已经有过介绍。作为应用程序之间唯一的共享数据的途经,Content Provider主要的功能是存储并检索数据,以及向其他应用提供访问数据的接口。

             Android系统为常见的系统数据类型(如音频,视频,图像,手机通讯录联系人信息等)内置了一系列的Content Provider ,这些都位于android.provider包下。持有特定的许可,可以在自己开发的应用程序访问这些Content Provider

             让自己的数据和其他的应用程序共享的方式有两种:创建自己的Content Provider(即继承自ContentProvider类)或者是将自己的数据添加到已有的Content Provider 中去,后者需要保证现有的Content Provider和自己的数据类型相同并且具有该Content Provider的写入权限。对于ContentProvider ,最终要的就是数据模型(data model)和URI。

        

       (1)数据模型(data model)

 

           Content Provider 将其存储的数据以数据表的形式提供给访问者,在数据表中每一行为一条记录,每一列具有特定类型和意义的数据。每一条数据记录都包括一个“——ID”数值字段,该字段唯一标识一条数据。

   

       (2)URI

 

            URI,每一个Content Provider都对外提供一个能够唯一标识自己数据集(data set)的公开URI,如果一个Content Provider管理多个数据集,其将会为每个数据集分配一个独立的URI。所有的Content Provider的URI都以“content://”开头,期中“content://”是用来标识数据是由Content Provider管理的scheme。

            几乎所有的Content provider的操作中都会用到URI,因此一般来讲,如果自己开发Content Provider,最好将URI定义为常量,这样在简化开发的同时也提高了代码的可维护性。

     

       首先介绍如何访问Content Provider中的数据,访问Content Provider中的数据主要通过ContentResolver类提供了成员方法可以用来对Content Provider中的数据进行查询,插入,修改和删除等操作。以查询为例,查询一个Content Provider需要掌握如下的信息:

     唯一标识Content Provider;需要访问的数据字段名称;该数据字段的数据类型(如果需要访问特定的某条数据记录,只需该记录的ID即可)

     查询Content Provider的方法有两个:ContentResolver的query()和Activity对象的managedQuery(),二者接收的参数相同,返回的都是Cursor对象,唯一的不同是使用managedQuery方法可以让Activity来管理Cursor的生命周期。

      被管理的Cursor会在Activity进入暂停状态的时候调用自己的deactivate方法自行卸载,而在Activity回到运行态时会调用自己的query方法重新查询生成的Cursor对象。如果一个未被管理的Cursor对象想要被Activity管理,可以调用Activity的startManagingCursor方法来实现。

       下面通过一个例子来说明访问Content Provider的方式:

       首先在手机模拟器上运行“联系人”程序,添加两个联系人。

       修改布局文件main.xml,改后代码如下:

<?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"
    >
<TextView 
    android:id="@+id/textView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
</LinearLayout>

Activity类代码如下:

package karant.zhan;

import android.R.integer;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Contacts.People;
import android.widget.TextView;

public class ContentProviderTest extends Activity {
 
 String [] columns = {                            //查询Content Provider时希望返回
   People._ID,
   People.NAME,
 };
 
 Uri contactUri = People.CONTENT_FILTER_URI;    //访问Content Provider需要Uri
 TextView textView;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        textView = (TextView)findViewById(R.id.textView);
        String result = getQueryData();                       //调用方法访问Content Provider
        textView.setText("ID/t名字/n" + result);              //将查询到的信息显示到TextView中
    }

 private String getQueryData() {
  String result =  "";
  ContentResolver resolver = getContentResolver();  //获取ContentResolver对象
  Cursor cursor = resolver.query(contactUri, columns, null, null, null);//调用方法查询Content Provider
  int idIndex = cursor.getColumnIndex(People._ID);   //获得额_ID字段的列索引
  int nameIndex = cursor.getColumnIndex(People.NAME);   //获得NAME字段的列索引
  for(cursor.moveToFirst(); (!cursor.isAfterLast()); cursor.moveToNext()){   //遍历Cursor,提取数据
   result = result + cursor.getString(idIndex) + "/t";
   result =  result +cursor.getString(nameIndex)  + "/t/n";
  }
  cursor.close();               //关闭Cursor对象
  return result;
 }
   
   
}

 

最后还要修改AndoridMainfest.xml代码,只需要加入下面一行代码
    <uses-permission android:name="android.permission.READ_CONTACTS"  />

 

 

 

             如果需要创建一个ContentProvider,则需要进行的工作主要分为下面三步:

 

        (1)建立数据的存储系统

               数据的存储系统可以由开发人员任意决定,一般来讲,大多数的Content Provider都通过Android的文件存储系统或SQLite数据库创建自己的数据库存储系统

        (2)扩展ContentProvider类。

               开发一个继承自ContentProvider类的子类代码来扩展ContentProvider类,在这个步骤主要工作是将要共享的数据包装并以ContentResolver和Cursor对象能够访问到的形式对外展示。具体来说需要实现ContentProvider类中的6个方法。

            Cursor query(Uri uri,String[] projection, String selection, String [] selectionArgs,String sortOrder):将查询的数据以Cursor对象形式返回。

            Uri insert(Uri uri,ContentValues values):向Content Provider 中插入新数据记录,ContentValues为数据记录的列名和列值的映射。

            int update(Uri uri,ContentValues values,String selection, String[] selectionArgs): 更新Content Provider中已存在的数据记录。

            int delete(Uri uri,String selection,String[] selectionArgs):从Content Provider中删除数据记录

            String getType(Uri uri):返回Content Provider中数据的(MIME)类型。

            boolean onCreate():当Content Provider启动被调用

         

     以上方法会在ContentProvider对象中被调用,所以很好地实现这些抽象方法会为ContentResolver提供一个完善的外部接口,除了实现抽象方法外,还可以做一些提高可用性的工作。

            定义一个URI类型的静态常量,命名为CONTENT_URI。 必须为改常量对象定义一个唯一的URI字符串,一般的做法是将ContentProvider子类的全程类名作为URI字符串,如“content://karant.zhan.Provider”

           定义每个字段的列名,如果采用的数据存储系统为SQLite数据库,数据表列名可以采用数据库中表的列名。不管数据表中有没有其他的唯一标识一条记录的字段,都应该定义一个“_id”字段来唯一标识一条记录。一般将这些列名字符串定义为静态常量,如“_id”字段名定义为一个名为“_ID”值为“_id”的 静态字符串对象

           (3)在应用程序的AndroidMainfest.xml文件声明Content Provider组件

               创建好一个Content Provider必须要在应用程序的AndroidMainfest.xml中进行声明,否则该应用程序Content Provider对于Android系统将是不可见的。声明一个Content Provider组件的方法在之前文章有所介绍,如果有一个名为MyProvider的类扩展了ContentProvider类,声明该组件的代码如下:

            <provider name = "karant.zhan.MyProvider"

                                          authorities = "karant.zhan.myprovider"

                         ....           />

             </provider>

       其中name属性为ContentProvider子类的全称类名,authorities属性标识了一个ContentProvider。

 

 

         6.  Preferences的使用

       Preferences是一种应用程序内部轻量级的数据存储方案。Preferences主要用于存储和查询简单数据类型的数据,这些简单的数据类型包括boolean,int , float,long 以及String等,存储方式为以键值对的心事存放在应用程序的私有文件夹下。

       Preferences一般用来存储应用程序的设置信息,如应用程序的色彩方案,文字文体等。在应用程序中获取Preferences的方式有一下两种:

         (1)调用Context对象的getSharedPreferences方法获得SharedPreferences对象,需要传入SharedPreferences的名称和打开模式,名称为Preferences文件的名称,如果不存在则创建一个以传入名称为名的新Preferences文件:打开模式为PRIVATE,MODEL_WORLD,READABLE和MODE_WORLD_WRITEABLE其中之一。

         (2)调用Activity对象的getPreferences方法获得SharedPreferences对象。需要传入打开模式,打开模式为PRIVATE,MODEL_WORLD,READABLE和MODE_WORLD_WRITEABLE其中之一。

         

         两种获得SharedPreferences对象的最大不同就是通过Contxt对象的getSharedPreferences方法获得的对象可以被同一个应用程序下其他组件共享,而使用Activity对象的getPreferences方法获得对象只能被调用该方法所在的Activity使用。

      SharedPreferences对象提供了一系列的get方法用于接收键返回对应的值,如果需要对Preferences文件中存储的键值进行修改,首先要调用SharedPreferences的edit方法获得一个Editor对象,该对象可以用来修改Preferences文件中存储的内容。

下面是一个Preferences的例子:

 

    需要一个控件在布局文件中添加,修改后布局文件main.xml如下:

package karant.zhan;

import android.app.Activity;
import android.os.Bundle;

public class PreferencesTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

 

Activity类代码如下:

 

package karant.zhan;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.EditText;

public class PreferencesTest extends Activity {
 
 EditText editText;         //EditText对象引用
 SharedPreferences sharedPreferences;   //SharedPreferences对象引用
 public final String EDIT_TEXT_KEY = "EDIT_TEXT";  //定义Preferences文件中的键
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        editText = (EditText)findViewById(R.id.editText);
        sharedPreferences = getPreferences(MODE_PRIVATE);  
        String result = sharedPreferences.getString(EDIT_TEXT_KEY, null);
        if(result != null){
         editText.setText(result);
        }
    }
   
    @Override
    protected void onDestroy() {
     SharedPreferences.Editor editor = sharedPreferences.edit();  //获得ShredPreferences的Editor对象
     editor.putString(EDIT_TEXT_KEY, String.valueOf(editText.getText()));//修改数据
     editor.commit();      //不许调用该方法提交修改
     
     super.onDestroy();
    }
}

 

 

 

原创粉丝点击