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

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

接上篇。

 

  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();
    }
}

 

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 二晓啊相公太爱我了怎么办全文免费 车牌被套牌了又有违章怎么办 高中生只学好主课副科学不好怎么办 母泰迪怀孕23天了不吃饭怎么办 媳妇一再触碰我的底线怎么办 发票商品编码好多选错了分类怎么办 吃了用福尔马林泡的食物怎么办 没大没小说话不尊重人的孩子怎么办 升级安卓8.0后app闪退怎么办 业主装门占用消防通道物业怎么办? 想改名字派出所不给改怎么办 物业不给地热打压影响装修怎么办 pos机pin效码验证错误怎么办 苹果下载东西要发验证码怎么办 接口断在了丝扣里面怎么办 政府下了一张关停取缔单怎么办 微信运动数据不刷新了怎么办 邻居霸占我的土地不还我该怎么办 双层水浴式杀菌锅阀门坏了怎么办 通下水管的钢丝断水管里了怎么办 塑料水管与水阀连接处漏水怎么办 介质流向标识管道温度太高怎么办 雪碧里气体太多瓶子涨得要炸怎么办 餐厅不清洗油烟管道物业该怎么办 用完权健洁净宝后奇痒的厉害怎么办 老房子铸铁暖气管从外锈蚀了怎么办 德意壁挂炉补水多了水压过高怎么办 新空调的散热片铜管漏了怎么办 猪舍被别人推掉漏电电到人怎么办? 网上买的燃气灶连接用软管怎么办 哈弗h3后减振器上支架坏了怎么办 汽车用收录机电机皮带断了怎么办 大便太粗把马桶堵了怎么办 大便过粗把马桶堵了怎么办 大便硬的像石头拉不出来怎么办 家里埋在地下的水管漏水怎么办 埋在墙里的水管漏水怎么办 开发商暗埋水管热熔接头漏水怎么办 钻墙把水管钻破了怎么办 钻墙时不小心把水管钻破了怎么办 孩子把同桌的铅笔盒弄坏了怎么办