首页 > 代码库 > 第五章 以数据为中心—数据存取(6)

第五章 以数据为中心—数据存取(6)

5.3 安全方便简单—使用SharedPreferences

前面操作文件和数据库都相对比较复杂,需要打开,读取,关闭等等操作。可能有人就想,如果我只是需要存取几个简单的数据,有没有简单点的方法呢?的确,在Android中也封装了一种轻便的数据存取的方法—Preferences。

Preferences是一种轻量级的数据存储机制,它将一些简单数据类型的数据,包括boolean类型、int类型、float类型、long类型以及String类型的数据,以键值对的形式存储在应用程序的私有Preferences目录(/data/data/<包名>/shared_prefs/)中。Preferences 只能在同一个包内使用,不能在不同的包之间使用。这种Preferences机制广泛应用于存储应用程序中的配置信息。

在Android平台上,只需要用一个Context的对象调用getSharedPreferences(String name,int mode)方法传入Preferences文件名和打开模式,就可以获得一个SharedPreferences的对象。若该Preferences文件不存在,在提交数据后会创建该Preferences文件。利用SharedPreferences对象可以调用一些getter方法,传入相应的键来读取数据。要对Preferences文件的数据进行修改,首先利用SharedPreferences对象调用edit()方法获得一个内部类Editor的对象,然后用这个Editor对象就可以对Preferences文件进行编辑了。注意,编译完毕后一定要调用commit()方法,这样才会把所做的修改提交到Preferences文件当中去。

下面是一个将EditText中的文本保存下来的例子:

// import略

public class PreferenceTest extends Activity {

 

    private EditText edit;

private static final String TEMP_NAME = "temp_name";

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        edit = new EditText(this);

        // 获得SharedPreferences对象 只读

        SharedPreferences pre =

        getSharedPreferences(TEMP_NAME, MODE_WORLD_READABLE);

        // 读取“content”

        String content = pre.getString("content","");

        edit.setText(content);

        setContentView(edit);

    }

    @Override

    protected void onStop() {

        super.onStop();

       // 获得SharedPreferences.Editor对象 可写的

        SharedPreferences.Editor editor = getSharedPreferences(TEMP_NAME,

                 MODE_WORLD_WRITEABLE).edit();

        // 保存“content”

        editor.putString("content", edit.getText().toString());

        // 提交数据

        editor.commit();

    }

}

 

关于方法“public SharedPreferences getSharedPreferences(String name, int mode);”做些说明:

第一个参数是文件名称,第二个参数是操作模式。其中操作模式有三种:MODE_PRIVATE(私有);MODE_WORLD_READABLE(可读);MODE_WORLD_WRITEABLE(可写)。

    可以看到,使用Preferences保存和读取数据非常的简单。

 

经验分享:

文件可以存储在SD卡上,而存储在SD卡上的文件,不会随着应用的卸载而被删除。但是Preferences保存的数据,如果应用被卸载了,其Preferences数据也就不存在了。这个是在使用Preferences保存数据时需要注意的。

 

5.4 我的数据大家用—ContentProvider、ContentResolver

在Android中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所拥有的数据库、文件、等等内容,都是不允许其他应用直接访问的,但有时候,沟通是必要的,不仅对第三方很重要,对应用自己也很重要。解决这个问题可以靠ContentProvider。

一个ContentProvider实现了一组标准的方法接口,从而能够让其他的应用保存或读取此ContentProvider的各种数据类型。也就是说,一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据暴露出去,而被别的程序看到。其他程序也可以通过这ContentProvider读取、修改、删除数据,当然,中间也会涉及到一些权限的问题。下边列举一些较常见的接口,这些接口如表5-3所示。

接口

说明

query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder)

通过Uri进行查询,返回一个Cursor。

insert(Uri url, ContentValues values)

将一组数据插入到Uri指定的地方。

update(Uri uri, ContentValues values, String where, String[] selectionArgs)

更新Uri指定位置的数据。

delete(Uri url, String where, String[] selectionArgs)

删除指定Uri并且符合一定条件的数据。

表5-3 ContentProvider的接口

 

经验分享:

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

 

外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity 当中通过getContentResolver()可以得到当前应用的ContentResolver实例。ContentResolver提供的接口和ContentProvider 中需要实现的接口对应,详细请参考表5-3。

在内容的提供者(ContentProvider)和使用者(ContentResolver)中我们都看到一个常用的对象Uri,这个对象类似一个地址,通常有两种,一种是指定全部数据,另一种是指定某个ID 的数据。我们看下面的例子。

content://contacts/people/ 这个Uri指定的就是全部的联系人数据。

content://contacts/people/1 这个Uri指定的是ID为1的联系人的数据。

 

Uri一般由3 部分组成:

l  第一部分是:"content://" 。

l  第二部分是要获得数据的一个字符串片段。

l  最后就是ID(如果没有指定ID,那么表示返回全部)。

由于 URI 经常比较长,而且有时候容易出错,且难以理解。所以,在Android 当中定义了一些辅助类,并且定义了一些常量来代替这些长字符串的使用,例如下边的代码:

Uri mUri = android.provider.Contacts.People.CONTENT_URI; //联系人的URI实际等于:

Uri mUri = Uri.parse("content://contacts/people");

 

--------------------------------------------
程序员赚钱不易 一定要学会理财
平安陆金所 隶属于平安集团的p2p平台
年投资回报率7%-9% 是替代银行理财的首选
个人经验 推荐投资安鑫或者有担保的彩虹项目
不要投资安e 那个几乎无法转让 想提前提现非常困难
网站链接 http://affiliate.lufax.com/action/36XBU
首次投资1000元即可额外赚几百元 不赚白不赚
--------------------------------------------

上述都是理论的分析,下面我们通过一个例子来看看具体是如何使用的,我们要获取出手机的联系人列表,将其显示出来。

// import略

public class ContentResolverTest extends Activity {

 

    // 查询Content Provider时希望返回的列

           private String[] columns = { ContactsContract.Contacts.DISPLAY_NAME,

             ContactsContract.Contacts._ID,};

    private Uri contactUri = ContactsContract.Contacts.CONTENT_URI;

    private TextView tv;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        tv = new TextView(this);

        String result = getQueryData();

        tv.setTextColor(Color.GREEN);

        tv.setTextSize(20.0f);

        tv.setText("ID   名字 " + result);

        setContentView(tv);

    }

    /**

     * 获取联系人列表的信息,返回 String对象

     */

    public String getQueryData() {

        String result = "";

        // 获取ContentResolver对象

        ContentResolver resolver = getContentResolver();

        Cursor cursor = resolver.query(contactUri, columns, null, null, null);

        // 获得_ID字段的索引

        int idIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);

        // 获得Name字段的索引

        int nameIndex = cursor

                 .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);

        // 遍历Cursor提取数据

        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {

             result = result + cursor.getString(idIndex) + ",";

             result = result + cursor.getString(nameIndex) + ";";

        }

        cursor.close();

        return result;

    }

}

 

经验分享:

联系人可能保存在手机中,也可能保存在手机卡中。上述代码只是从手机中获取了联系人的列表。在实际开发中,如果有这种需求,我们还需要从手机卡中获取所有联系人,并且与手机中的联系人做对比,最终得到一份完整的联系人列表。具体如何从手机卡中获取联系人,这里不做说明,读者可以从互联网查找相关资料。

 

经验分享:

在Android开发中,如果需要访问硬件设备,就经常会遇到权限问题。如果在调试过程中出现类似“Android Permission denied”错误,就要看看是否用到了系统功能而没有增加相应的权限。

比如,上面的例子,我们就需要添加相应的权限。

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

<!-- 读取联系人权限 -->

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

<!-- 写联系人权限 -->

第五章 以数据为中心—数据存取(6)