Android数据存储机制

数据是应用的核心。下面我们来详细看看Android系统的数据存储和共享机制。

Android为我们提供了4种数据存储方式,但由于存储的这些数据都是某个应用程序私有的,所以它又为我们提供了一种在不同应用程序之间共享数据的机制,即ContentProvider。

下面我们首先将分别介绍Android的4种数据存储方式:Shared Preferences、Files、SQLite、NetWork,最后我们将详细介绍Android的Content Provider机制。

一、Android数据存储之SharedProviences
它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值对的方式存储,可以简单的读取与写入,具体实例如下:
//读取SharedPreference
void  readSharedPreferences()
{
    String  strName,strPassword;
    SharedPreferences   user = getSharedPreferences(“user_info”,0);
    strName = user.getString(“NAME”,””);
    strPassword = user getString(“PASSWORD”,””);
}
//往SharedPreference中写入内容
void  writeSharedPreferences(String  strName,String strPassword)
{
    SharedPreferences   user = getSharedPreferences(“user_info”,0);
    //使其处于编辑状态
    uer.edit();
    user.putString(“NAME”, strName);
    user.putString(“PASSWORD” ,strPassword);
    user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data/<package name>/shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:
<?xml version=”1.0″ encoding=”UTF-8″?>
<map>
    <string name=”NAME”>moandroid</string>
    <string name=” PASSWORD”>SharedPreferences</string>
</map>
使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用

二、Android数据存储之Files(文件)
文件方式是一种较常用的存储方法,在Android中读/写文件的方法,与Java中实现I/O的程序是完全一样的,Android为我们提供了openFileInput()和openFileOutput()方法来读取设备上的文件。具体示例如下:
//读文件
private void read() {  
        try {  
            FileInputStream inputStream = this.openFileInput("music.cfg");  
            byte[] bytes = new byte[1024];  
            ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();  
            while (inputStream.read(bytes) != -1) {  
                arrayOutputStream.write(bytes, 0, bytes.length);  
            }  
            inputStream.close();  
            arrayOutputStream.close();  
            mbMusic = Boolean.getBoolean(new String(arrayOutputStream.toByteArray()));  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
//写文件
private void writeFile() {  
    try {  
        /** 根据用户提供的文件名,以及文件的应用模式,打开一个输出流
         * openFileOutput(String name, int mode);
         * 第一个参数,代表文件名称,注意这里的文件名称不能包括任何的/或者/这种分隔符,只能是文件名
         *          该文件会被保存在/data/data/应用名称/files/music.cfg
         * 第二个参数,代表文件的操作模式
         *          MODE_PRIVATE 私有(只能创建它的应用访问) 重复写入时会文件覆盖
         *          MODE_APPEND  私有   重复写入时会在文件的末尾进行追加,而不是覆盖掉原来的文件
         *          MODE_WORLD_READABLE 公用  可读
         *          MODE_WORLD_WRITEABLE 公用 可读写
         *  
         */  
        FileOutputStream outputStream = openFileOutput("music.cfg",  
            Activity.MODE_PRIVATE);  
        outputStream.write(String.valueOf(mbMusic).getBytes());  
        outputStream.flush();  
        outputStream.close();  
        Toast.makeText(FilesTest.this, "保存成功", Toast.LENGTH_LONG).show();  
    } catch (FileNotFoundException e) {  
        e.printStackTrace();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  
} 
如果在开发一个应用时,需要通过加载一个文件的内容来初始化程序,就可以在编译程序之前,在/res/raw/tempFile中建立一个文件,然后直接读取内容(具体方法参见本人另一片文章:Android各种资源详解 )。
对于sd卡上的文件读写,可以File file = new File("/sdcard/");然后遍历sdcard目录,对其中文件进行相关操作,具体方法不再赘述。
三、 Android数据存储之NetWork
通过网络方式来获取和保存数据资源,需要设备保持联网状态。将数据存储到网络的方法很多,如:将要保存的数据以文件方式上传到文件服务器、发送电子邮件等等。
也可以将网络上的资源获取到本地。下面的例子是一个将网络上的文件获取到本地并显示。
try{
    URL uri = new URL("http://192.168.2.22:8080/test.txt");
    URLConnection con = uri.openConnection();
    InputStream is = con.getInputStream();
    BufferedInputStream bis = new BufferedInputStream(is);
    ByteArrayBuffer baf = new ByteArrayBuffer(100);
    int current = 0;
    while ((current = bis.read()) != -1){
        baf.append((byte)current);
    }
    text = new String(baf.toByteArray());
}catch (Exception e){
    text = e.getMessage();
}
textView.setText(text);
再来看看如何访问web网页,代码如下:
public class WebViewTest extends Activity {
    private WebView webView;
    /** Called when the activity is first created. */  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
 
        WebView wView = (WebView)findViewById(R.id.webview);     
        WebSettings wSet = wView.getSettings();     
        wSet.setJavaScriptEnabled(true);
        //解决乱码问题
        wSet.setDefaultTextEncodingName("utf-8");  
        
        //打开本包内asset目录下的index.html文件
        wView.loadUrl("file:///android_asset/index.html");   
        
        //打开本地sd卡内的index.html文件
        //wView.loadUrl("content://com.android.htmlfileprovider/sdcard/index.html");
        
        //打开指定url的html文件
        //wView.loadUrl("http://wap.baidu.com");  
    }  
}
布局文件如下:
<?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:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
<WebView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:id="@+id/webview"
/>
</LinearLayout>
在/assets/目录下建一文件名为:index.html
<html>
<head>
<title><h3>my first web page</h3></title>
</head>
<body>
<form method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password"></td>
</tr>
<tr>
<td><input type="button" value="重置" οnclick="alert('确认重置吗?');"></td>
<td><input type="button" value="登录" οnclick="alert('确认登录吗?');"></td>
</tr>
</form>
</body>
</html>
运行项目结果如图所示:


在Android访问网络时要注意:

(1)、android访问网络资源必须要有:<uses-permission android:name="android.permission.INTERNET" />权限,不然运行会提示:Permission denied。
(2)、若使用Android模拟器访问本地机器,不能用localhost或者127.0.0.1,而要用10.0.2.2,不然会连接不上,这是因为android模拟器(simulator)把它自己作为了localhost,也就是说,代码中使用localhost或者127.0.0.1来访问,都是访问模拟器自己;如果你想在模拟器上面访问你的电脑,那么就使用android内置的IP10.0.2.2吧。
四、Android数据存储之SQLite
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
下面试一个例子,通过它我们来看看有关SQLite数据库的CRUD等操作。
布局文件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"
    >
<ListView
    android:id="@+id/listView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>
</LinearLayout>
布局文件:listitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearlayout"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView
        android:id="@+id/ItemTitle"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    />
    <TextView
        android:id="@+id/ItemText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    />
</LinearLayout>
Java类:
public class SqlLiteTest extends Activity {
    private ListView listView;
    //记录条数
    private static int count = 0;
    //数据库对象
    private SQLiteDatabase sqliteDatabase;
    private final static String DATABASE_NAME = "sql.db";
    private final static String TABLE_NAME = "t_student";
    
    private final static String ID = "_id";
    private final static String NUM = "num";
    private final static String DATA = "data";
    //建表语句
    private final static String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME
                                                + "(" + ID + " INTEGER PRIMARY KEY,"
                                                + NUM + " INTEGER," + DATA + " TEXT)";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        listView = (ListView)findViewById(R.id.listView);
        //打开数据库
        sqliteDatabase = this.openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
        
        deleteTable();
        //创建表
        sqliteDatabase.execSQL(CREATE_TABLE);
        //更新ListView
        updateAdapter();
    }
    //按键监听
    public boolean onKeyUp(int keyCode,KeyEvent evnet){
        switch (keyCode){
            case KeyEvent.KEYCODE_DPAD_UP:
                addData();
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                delete();
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                updateData();
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                deleteTable();
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                deleteDataBase();
                break;
        }
        return true;
    }
    //更新listView视图
    private void updateAdapter(){
        Cursor cursor = sqliteDatabase.query(TABLE_NAME, new String[]{ID,NUM,DATA}, null, null, null, null, null);
        
        count = cursor.getCount();
        if (null != cursor && count >= 0){
            //ListAdapter 是ListView 和数据的桥梁
            ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.listitem, cursor, new String[]{NUM,DATA}, new int[]{R.id.ItemTitle,R.id.ItemText});
            
            //将adapter添加到listView中
            listView.setAdapter(adapter);
        }
    }
    //插入数据
    private void addData(){
        //要更新的数据
        ContentValues contentValue = new ContentValues();
        contentValue.put(NUM, count);
        contentValue.put(DATA,"测试数据库数据:" + count);
        //插入数据
        sqliteDatabase.insert(TABLE_NAME, null, contentValue);
        count++;
        updateAdapter();
    }
    //删除数据库
    private void deleteDataBase(){
        this.deleteDatabase(DATABASE_NAME);
        this.finish();
    }
    //删除表
    private void deleteTable(){
        sqliteDatabase.execSQL("drop table if exists " + "sql." + TABLE_NAME);
        //this.finish();
    }
    //更新一条数据
    private  void updateData(){
        //要更新的数据
        ContentValues contentValue = new ContentValues();
        contentValue.put(NUM, count);
        contentValue.put(DATA,"修改后的数据:" + count);
        //执行更改
        sqliteDatabase.update(TABLE_NAME, contentValue, NUM + "=" + Integer.toString(count - 1), null);
        //更新ListView数据
        updateAdapter();
    }
    //删除指定的数据
    private void delete(){
        sqliteDatabase.execSQL("delete from " + TABLE_NAME + " where _id = " + Integer.toString(count));
        count--;
        if (count < 0){
            count = 0;
        }
        updateAdapter();
    }
}
运行,按上下左右键分别进行,增加,删除,修改以及删除数据库操作。结果如下图所示:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值