Android笔记----Android的数据存储和IO操作

来源:互联网 发布:linux 服务器重启 编辑:程序博客网 时间:2024/06/05 06:09

使用SharedPreferences

File存储

SQLite数据库

使用SharedPreferences

1.1 SharedPreferences与Editor简介

应用程序有少量的数据需要保存,而且这些数据的格式很简单,都是普通的字符串、标量类型的值等,比如应用程序的各种配置信息,对于这种数据,Android提供了SharedPreferences。

SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此它保存的数据主要是简单类型的key-value对。 SharedPreferences接口主要负责读取应用程序的Preferences数据,它提供了如下常方法来访问SharedPreferences中的key-value对。

boolean contains(String key):判断SharedPreferences是否包含特定key的数据。

abstract MapgetAll():获取SharedPreferences数据里全部的key-value对。

boolean getXxx(String key,xxx defValue):获取SharedPreferences数据里指定的key对应的value。如果key值不存在,返回默认值defValue。其中xxx可以是boolean、float、int、long、String等各种基本类型的值。

SharedPreferences接口本身并没有提供写入数据的能力,而是通过SharedPreferences的内部接口, SharedPreferences调用edit()方法即可获取它所对应的Editor对象,提供了如下方法向SharedPreferences写入数据。

SharedPreferences.Editor clear():清空SharedPreferences里所有数据。

SharedPreferences.Editor putXxx(String key, xxx value):向SharedPreferences存入指定key对应的数据。其中xxx可以是boolean、float、int、long、String等各种基本类型的值。

SharedPreferences.Editor remove(String key):删除SharedPreferences里指定的key对应的数据项。

boolean commit() :当Editor编辑完成后,调用该方法提交修改。

SharedPreferences是一个接口,程序无法直接创建其实例,只能通过Context提供的getSharedPreferences(String name,int mode) 方法来获取SharedPreferences实例。该方法的第二个参数支持如下几个值。

Context.MODE_PRIVATE:指定SharedPreferences数据只能被本应用程序读、写。

Context.MODE_WORLD_READABLE:指定SharedPreferences数据能被其他应用程读,但不能写。

Context.MODE_WORLD_WRITEABLE:指定SharedPreferences数据能被其他应用程读、写。

例:SharedPreferences的存储位置和格式:

SharedPreferencesDemo.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
publicclass SharedPreferencesDemo extendsActivity
{
    SharedPreferences preferences;
    SharedPreferences.Editor editor;
 
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取只能被本应用程序读、写的SharedPreferences对象
        preferences = getSharedPreferences("hello", MODE_WORLD_READABLE);
        editor = preferences.edit();
        Button read = (Button) findViewById(R.id.read);
        Button write = (Button) findViewById(R.id.write);
        read.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View arg0)
            {
                //读取字符串数据
                String time = preferences.getString("time",null);
                //读取int类型的数据
                intrandNum = preferences.getInt("random",0);
                String result = time == null? "您暂时还未写入数据"
                    :"写入时间为:"+ time
                    +"\n上次生成的随机数为:"+ randNum;
                //使用Toast提示信息
                Toast.makeText(SharedPreferencesTest.this,
                    result , 5000)
                    .show();
            }
        });
        write.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View arg0)
            {
                SimpleDateFormat sdf = newSimpleDateFormat("yyyy年MM月dd日 "
                    +"hh:mm:ss");
                // 存入当前时间
                editor.putString("time", sdf.format(newDate()));
                // 存入一个随机数
                editor.putInt("random", (int) (Math.random() * 100));
                // 提交所有存入的数据
                editor.commit();
            }
        });
    }
}


运行程序后,点击“写入数据”,程序将完成SharedPreferences写入写入完成后,打开DDMS的File Explorer面板,SharedPreferences数据保存在/data/datta/com.whq/shared_prefs目录下, SharedPreferences数据是以XML格式保存。

1.2 要读、写其他应用的SharedPreferences

要读、写其他应用的SharedPreferences,前提是创建该SharedPreferences的应用程序指定相应的访问权限,例如指定了MODE_WORLD_READABLE,这表明该SharedPreferences可被其他应用程序读取;指定MODE_WORLD_WRITEABLE,这表明该SharedPreferences可被其他程序写入。

为了读取其他程序的SharedPreferences,可按如下步骤进行。

需要创建其他程序对应的Context。

调用其他应用程序的Context的getSharedPreferences(String name,int mode) 即可获取相应的SharedPreferences对象。

如果需要向其他应用的SharedPreferences数据写入数据,调用SharedPreferences的edit()方法获取相应的Editor即可。

例:读取其他应用程序的SharedPreferences数据:

UseCount .java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
packagecom.Xxx;
publicclass UseCount extendsActivity
{
    SharedPreferences preferences;
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        preferences = getSharedPreferences("count", MODE_WORLD_READABLE);
        //读取SharedPreferences里的count数据
        intcount = preferences.getInt("count", 0);
        //显示程序以前使用的次数
        Toast.makeText(this,
            "程序以前被使用了"+ count + "次。",10000)
            .show();
        Editor editor = preferences.edit();
        //存入数据
        editor.putInt("count", ++count);
        //提交修改
        editor.commit();   
    }
}

ReadOtherPreferences.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
publicclass ReadOtherPreferences extendsActivity
{
    Context useCount;
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //Context useCount = null;
        try
        {
           // 获取其他程序所对应的Context(com.Xxx:UseCount所在包名)
            useCount = createPackageContext("com.Xxx",
                Context.CONTEXT_IGNORE_SECURITY);
        }
        catch(NameNotFoundException e)
        {
            e.printStackTrace();
        }
        // 使用其他程序的Context获取对应的SharedPreferences
        SharedPreferences prefs = useCount.getSharedPreferences("count",
            Context.MODE_WORLD_READABLE);
        // 读取数据
        intcount = prefs.getInt("count",0);
        TextView show = (TextView) findViewById(R.id.show);
        // 显示读取的数据内容
        show.setText("UseCount应用程序以前被使用了"+ count + "次。");
    }
}


File存储

2.1 openFileOutput和openFileInput

Context提供了如下两个方法来打开本应用程序的数据文件夹里的文件IO流。

FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流。

FileOutputStream openFileOutput(String name,int mode):打开应用程序的数据文件夹下的name文件对应输出流。

上面两个方法分别用于打开文件输入流、输出流。其中第二个方法的第二个参数指定打开文件夹的模式,该模式支持如下值。

MODE_PRIVATE:该文件只能被当前程序读写。

MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件追加内容。

MODE_WORLD_READABLE:该文件的内容可以被其他程序读取。

MODE_WORLD_WRITEABLE:该文件的内容可由其他程序读写。

Context还提供了如下几个方法来访问应用程序的数据文件夹。

getDir(String name,int mode):在应用程序的数据文件夹下获取或创建name对应的子目录。

File getFilesDir():获取该应用程序的数据文件夹的绝对路径。

String[] fileList():返回该应用程序的数据文件夹下的全部文件。

deleteFile(String):删除该应用程序的数据文件夹下的指定内容。

例:读写应用程序数据文件夹下内容:

\

Main.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
<!--?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"android:orientation="vertical">
 
    <edittext android:id="@+id/edit1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:lines="4">
 
    <button android:id="@+id/write"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/write">
 
    <edittext android:id="@+id/edit2"android:layout_width="fill_parent"android:layout_height="wrap_content"android:cursorvisible="false"android:editable="false"android:lines="4">
 
    </edittext></button><button android:id="@+id/read"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/read">
 
</button></edittext></linearlayout>

FileTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
publicclass FileTest extendsActivity
{
    finalString FILE_NAME = "test.txt";
 
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        System.out.println(newStringBuilder("a").append("b").append("c")
            .toString());
        // 获取两个按钮
        Button read = (Button) findViewById(R.id.read);
        Button write = (Button) findViewById(R.id.write);
        // 获取两个文本框
        finalEditText edit1 = (EditText) findViewById(R.id.edit1);
        finalEditText edit2 = (EditText) findViewById(R.id.edit2);
        // 为write按钮绑定事件监听器
        write.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View source)
            {
                // 将edit1中的内容写入文件中
                write(edit1.getText().toString());
                edit1.setText("");
            }
        });
 
        read.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View v)
            {
                // 读取指定文件中的内容,并显示出来
                edit2.setText(read());
            }
        });
    }
 
    privateString read()
    {
        try
        {
            // 打开文件输入流
            FileInputStream fis = openFileInput(FILE_NAME);
            byte[] buff = newbyte[1024];
            inthasRead = 0;
            StringBuilder sb = newStringBuilder("");
            while((hasRead = fis.read(buff)) > 0)
            {
                sb.append(newString(buff, 0, hasRead));
            }
            returnsb.toString();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        returnnull;
    }
 
    privatevoid write(String content)
    {
        try
        {
            // 以追加模式打开文件输出流
            FileOutputStream fos = openFileOutput(FILE_NAME, MODE_APPEND);
            // 将FileOutputStream包装成PrintStream
            PrintStream ps = newPrintStream(fos);
            // 输出文件内容
            ps.println(content);
            ps.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}


注:test.txt所在位置:打开File Explorer:data/data/com.Xxx包名/file/test.txt

2.2 读写SD卡上的文件

当程序通过Context的openFileInput或openFileOutput来打开文件输入流、输出流时,程序所打开的都是应用程序的数据文件夹里的文件,这样所存储的文件大小可能比较有限。为了更好的存、取应用程序的大文件数据,应用程序需要读、写SD卡上的文件。步骤如下:

调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。

调用Environment的getExternalStorageDirectory()方法来获取SD卡的目录。

使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡里的文件。

例:读写SD卡的内容:

SDCardTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
publicclass SDCardTest extendsActivity
{
    finalString FILE_NAME = "/test.txt";
 
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取两个按钮
        Button read = (Button) findViewById(R.id.read);
        Button write = (Button) findViewById(R.id.write);
        // 获取两个文本框
        finalEditText edit1 = (EditText) findViewById(R.id.edit1);
        finalEditText edit2 = (EditText) findViewById(R.id.edit2);
        // 为write按钮绑定事件监听器
        write.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View source)
            {
                // 将edit1中的内容写入文件中
                write(edit1.getText().toString());
                edit1.setText("");
            }
        });
 
        read.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View v)
            {
                // 读取指定文件中的内容,并显示出来
                edit2.setText(read());
            }
        });
    }
 
    privateString read()
    {
        try
        {
            //如果手机插入了SD卡,而且应用程序具有访问SD的权限
            if(Environment.getExternalStorageState()
                .equals(Environment.MEDIA_MOUNTED))
            {
                //获取SD卡对应的存储目录
                File sdCardDir = Environment.getExternalStorageDirectory();
                //获取指定文件对应的输入流
                FileInputStream fis = newFileInputStream(sdCardDir
                    .getCanonicalPath() + FILE_NAME);
                //将指定输入流包装成BufferedReader
                BufferedReader br = newBufferedReader(new
                    InputStreamReader(fis));
                StringBuilder sb = newStringBuilder("");
                String line = null;
                while((line = br.readLine()) != null)
                {
                    sb.append(line);
                }
                returnsb.toString();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        returnnull;
    }
 
    privatevoid write(String content)
    {
        try
        {  
            //如果手机插入了SD卡,而且应用程序具有访问SD的权限
            if(Environment.getExternalStorageState()
                .equals(Environment.MEDIA_MOUNTED))
            {
                //获取SD卡的目录
                File sdCardDir = Environment.getExternalStorageDirectory();
                File targetFile = newFile(sdCardDir.getCanonicalPath()
                    + FILE_NAME);
                //以指定文件创建   RandomAccessFile对象
                RandomAccessFile raf = newRandomAccessFile(
                    targetFile , "rw");
                //将文件记录指针移动到最后
                raf.seek(targetFile.length());
                // 输出文件内容
                raf.write(content.getBytes());
                raf.close();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}


应用程序读、写SD卡文件请注意:

Android模拟器可通过mksdcard命令来创建虚拟存储卡

为了读写SD卡上的数据,必须在应用程序的AndroidManifest.xml中添加读写SD卡的权限。配置内容如下:

SQLite数据库

Android系统集成了一个轻量级的数据库:SQLite,SQLite只是一个嵌入式的数据库引擎,专门适用于资源有限的设备上(如手机、PDA等)适量数据存取。 SQLite数据库只是一个文件,不需要安装、启动服务器进程。

3.1 简介SQLiteDatabase

Android提供了SQLiteDatabase代表一个数据库(底层就是一个数据库文件),一旦应用程序获得了代表指定数据库的SQLiteDatabase对象,接下来就可以管理、操作数据库了。

SQLiteDatabase提供了如下静态方法来打开一个文件对应的数据库

SQLiteDatabase openDatabase(String path, SQLiteDatabase. CursorFactory factroy, int flags):打开path文件所代表SQLite数据库。

SQLiteDatabase openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory):打开或创建(如果 不存在)path文件所代表SQLite数据库。

在程序中获取SQLiteDatabase对象后,接下来就可调用其如下方法来操作数据库。

execSQL(String sql,Object[] bindArgs):执行带占位符的SQL语句。

execSQL(String sql):执行SQL语句。

insert(String table,String nullColumnHack,ContentValues values):向执行表中插入数据。

update(String table,ContentValues values,String whereClause,String[] whereArgs):更新指定数据库。

delete(String table,String whereClause,String[] whereArgs):删除指定表中的特定数据。

Cursor query(String table,String[] columns,String selection, String[] selectionArgs,String groupBy,String having,String orderBy):对执行数据表执行查询。

Cursor query(String table,String[] columns,String selection, String[] selectionArgs,String groupBy,String having,String orderBy,String limit):对执行数据表执行查询,limit对数控制最多查询几条记录。

rawQuery(String sql,String[] selectionArgs):执行带占位符的SQL查询。

begin Transaction():开始事务。

end Transaction():结束事务。

上面查询方法都是返回一个Cursor对象,Android中的Cursor类似于JDBC的ResultSet,Cursor提供如下方法来移动查询结果的记录指针。

move(int offset):将记录指针向上或向下移动指定的行数.

boolean moveToFirst():将记录指针移到到第一行。

boolean moveToLast():将记录指针移到到最后一行。

boolean moveToNext():将记录指针移到到下一行。

boolean moveToPosition(int position):将记录指针移到到指定行。

boolean moveToPrevious():将记录指针移到到上一行。

一旦记录指针移到到指定行后,接下来就可以调用Cursor的getXxx()方法来获取该行的指定列的数据。

3.2 创建数据库和表

使用SQLiteDatabase的静态方法即可打开或创建数据库,例如如下代码:

SQLiteDatabase.openOrCreateDatabase(“/mt/db/temp.db3”,null);

上面的代码即可返回一个SQLiteDatabase对象,该对象的execSQL可执行任意的SQL语句,因此程序可通过如下代码在程序中创建数据表:

//定义建表语句

sql=“create table user_inf(user_id integer primary key,”+” user_name varchar(255),”+”user_pass varchar(255))”

//执行SQL语句

db.execSQL(sql);

在程序中执行上面的代码即可在数据库中创建一个数据表。

3.3使用SQL语句操作SQLite数据库

使用SQLiteDatabase进行数据库操作的步骤如下:

获取SQLiteDatabase对象,进行与数据库连接。

调用SQLiteDatabase的方法来执行SQL语句。

操作SQL语句的执行结果,比如用SimpleCursorAdapter封装成Cursor。

调用close()方法,关闭SQLiteDatabase数据库,回收资源。

例:

DBTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
publicclass DBTest extendsActivity
{
    SQLiteDatabase db;
    Button bn = null;
    ListView listView;
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);     
        //创建或打开数据库(此处需要使用绝对路径)
        db = SQLiteDatabase.openOrCreateDatabase(this.getFilesDir()
            .toString() + "/test.db3", null);     
        listView = (ListView)findViewById(R.id.show);
        bn = (Button)findViewById(R.id.ok);
        bn.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View source)
            {
        //获取用户输入
        String title = ((EditText)findViewById(R.id.title))
            .getText().toString();
        String content = ((EditText)findViewById(R.id.content))
            .getText().toString();
        try
        {
            insertData(db , title , content);
            Cursor cursor = db.rawQuery("select * from news_inf",null);
            inflateList(cursor);
        }
        catch(SQLiteException  se)
        {
            //执行DDL创建数据表
        db.execSQL("create table news_inf(_id integer primary key autoincrement,"
            +" news_title varchar(50),"
            +" news_content varchar(255))");
        //执行insert语句插入数据
        insertData(db , title , content);
        //执行查询
        Cursor cursor = db.rawQuery("select * from news_inf",null);
        inflateList(cursor);
        }
    }          
        });    
    }
    privatevoid insertData(SQLiteDatabase db
        , String title , String content)
    {
        //执行插入语句
        db.execSQL("insert into news_inf values(null , ? , ?)"
            ,newString[]{title , content});
    }
    privatevoid inflateList(Cursor cursor)
    {
        //填充SimpleCursorAdapter
        SimpleCursorAdapter adapter = newSimpleCursorAdapter(
            DBTest.this, R.layout.line, cursor
            ,newString[]{"news_title", "news_content"}
            ,newint[]{R.id.my_title , R.id.my_content});
        //显示数据
        listView.setAdapter(adapter);
    }
    @Override
    publicvoid onDestroy()
    {
        super.onDestroy();
        //退出程序时关闭SQLiteDatabase
        if(db != null&& db.isOpen())
        {
            db.close();
        }
    }
}


Main.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
<!--?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"android:orientation="vertical">
 
    <edittext android:id="@+id/title"android:layout_width="fill_parent"android:layout_height="wrap_content">
 
    <edittext android:id="@+id/content"android:layout_width="fill_parent"android:layout_height="wrap_content"android:lines="2">
 
    <button android:id="@+id/ok"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/insert">
 
    <listview android:id="@+id/show"android:layout_width="fill_parent"android:layout_height="fill_parent">
 
</listview></button></edittext></edittext></linearlayout>

3.4使用sqlite3工具

在Android SDK的tools目录下提供了一个sqlite.exe,它是一个简单的SQLite数据库管理工具,利用该工具可以来查询、管理数据库。

SQLilte内部只支持NULL、INTEGER、REAL、TEXT和BLOB这5种数据类型。

它允许把各种类型的数据保存到任务类型的字段中,不必关心声明该字段所使用的数据类型。

SQLilte允许存入数据时忽略底层数据列实际的数据类型。

3.5 使用特定方法操作数据库

1.使用insert方法插入记录。

SQLiteDatabase的insert方法long insert(String table,String nullCoumnHack,ContentValues values)

table:代表要插入数据的表名

nullCoumnHack:代表强行插入null值的数据列的列名。

values:代表一行记录的数据。

insert方法插入的一条记录使用ContentValues存放,ContentValues类似于Map,提供了put(String key,Xxx value)方法存入数据。getAsXxx(String key)方法取出数据。

2.使用update方法更新记录

SQLiteDatabase的update方法为update(String table,ContentValues values,String whereClause,String[] whereArgs),该方法返回受此update语句影响的记录的条数。

table:代表要更新数据的表名

values:代表想更新的数据。

whereClause:满足该whereClause子句的记录将会被更新。

whereArgs:用于为whereClause子句传入参数。

3.使用delete方法删除记录

SQLiteDatabase的delete方法为delete(String table,String whereClause,String[] whereArgs),该方法返回受此delete语句影响的记录的条数。

table:代表要删除数据的表名

whereClause:满足该whereClause子句的记录将会被删除。

whereArgs:用于为whereClause子句传入参数。

4.使用query方法查询记录

SQLiteDatabase的query方法的签名为Cusor query(boolean distinct,String table,String[] columns,String selection, String[] selectionArgs,String groupBy,String having,String orderBy,String limit):参数说明如下。

distinct:指定是否去除重复记录。

table:代表查询数据的表名。

columns:要查询出来的列名。

selection:查询条件子句。

selectionArgs:占位符传入参数值。

groupBy:用于控制分组。

having:用于对分组进行过滤。

orderBy:用于对记录进行排序。

limit:用于进行分页。

3.6 SQLiteOpenHelper

SQLiteOpenHelper是一个辅助类,可用于管理数据库的创建和版本更新。SQLiteOpenHelper是个抽象类,一般的用法是创建SQLiteOpenHelper的子类,并重写它的onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)方法。

SQLiteOpenHelper包含如下常用方法:

getReadableDatabase():以读写的方法打开数据库对应SQLiteDatabase对象。

getWritableDatabase():以写的方法打开数据库对应SQLiteDatabase对象。

onCreate():当第一次创建数据库时回调该方法。

onUpgrade():当数据库版本更新时回调该方法。

close():关闭所打开的SQLiteDatabase对象

例子:简单生词本

\

MyDatabaseHelper.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
publicclass MyDatabaseHelper extendsSQLiteOpenHelper
{
    finalString CREATE_TABLE_SQL =
        "create table dict(_id integer primary key autoincrement , word , detail)";
    publicMyDatabaseHelper(Context context, String name, intversion)
    {
        super(context, name, null, version);
    }
    @Override
    publicvoid onCreate(SQLiteDatabase db)
    {
        // 第一个使用数据库时自动建表
        db.execSQL(CREATE_TABLE_SQL);
    }
    @Override
    publicvoid onUpgrade(SQLiteDatabase db, intoldVersion, intnewVersion)
    {
        System.out.println("--------onUpdate Called--------"
            + oldVersion + "--->"+ newVersion);
    }
}


Dict.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
publicclass Dict extendsActivity
{
    MyDatabaseHelper dbHelper;
    Button insert = null;
    Button search = null;
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);     
        // 创建MyDatabaseHelper对象,指定数据库版本为1,此处使用相对路径即可,
        // 数据库文件自动会保存在程序的数据文件夹的databases目录下。
        dbHelper = newMyDatabaseHelper(this
            ,"myDict.db3", 1);
        insert = (Button)findViewById(R.id.insert);
        search = (Button)findViewById(R.id.search);
        insert.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View source)
            {
                //获取用户输入
                String word = ((EditText)findViewById(R.id.word))
                    .getText().toString();
                String detail = ((EditText)findViewById(R.id.detail))
                    .getText().toString();
                //插入生词记录
                insertData(dbHelper.getReadableDatabase() , word , detail);
                //显示提示信息
                Toast.makeText(Dict.this,"添加生词成功!", 8000)
                    .show();
            }          
        });
 
        search.setOnClickListener(newOnClickListener()
        {
            @Override
            publicvoid onClick(View source)
            {
                // 获取用户输入
                String key = ((EditText) findViewById(R.id.key)).getText()
                    .toString();
                // 执行查询
                Cursor cursor = dbHelper.getReadableDatabase().rawQuery(
                    "select * from dict where word like ? or detail like ?",
                    newString[]{"%"+ key + "%", "%"+ key + "%"});              
        //创建一个Bundle对象
        Bundle data = newBundle();
        data.putSerializable("data", converCursorToList(cursor));
        //创建一个Intent
        Intent intent = newIntent(Dict.this
            , ResultActivity.class);
        intent.putExtras(data);
        //启动Activity
        startActivity(intent);
            }
        });
    }
    protectedArrayList<map<string ,=""string="">>
        converCursorToList(Cursor cursor)
    {
        ArrayList<map<string ,=""string="">> result =
            newArrayList<map<string ,=""string="">>();
        //遍历Cursor结果集
        while(cursor.moveToNext())
        {
            //将结果集中的数据存入ArrayList中
            Map<string ,=""string=""> map = new
                HashMap<string ,=""string="">();
            //取出查询记录中第2列、第3列的值
            map.put("word", cursor.getString(1));
            map.put("detail", cursor.getString(2));
            result.add(map);
        }
        returnresult;     
    }
    privatevoid insertData(SQLiteDatabase db
        , String word , String detail)
    {
        //执行插入语句
        db.execSQL("insert into dict values(null , ? , ?)"
            ,newString[]{word , detail});
    }
    @Override
    publicvoid onDestroy()
    {
        super.onDestroy();
        //退出程序时关闭MyDatabaseHelper里的SQLiteDatabase
        if(dbHelper != null)
        {
            dbHelper.close();
        }}}</string></string></map<string></map<string></map<string>

ResultActivity.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
publicclass ResultActivity extendsActivity
{
    @Override
    publicvoid onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popup);
        ListView listView = (ListView)findViewById(R.id.show);
        Intent intent = getIntent();
        //获取该intent所携带的数据
        Bundle data = intent.getExtras();
        //从Bundle数据包中取出数据
        @SuppressWarnings("unchecked")
        List<map<string ,=""string="">> list =
            (List<map<string ,=""string="">>)data.getSerializable("data");
        //将List封装成SimpleAdapter
        SimpleAdapter adapter = newSimpleAdapter(
            ResultActivity.this, list
            , R.layout.line , newString[]{"word", "detail"}
            ,newint[]{R.id.word , R.id.detail});
        //填充ListView
        listView.setAdapter(adapter);
    }
}</map<string></map<string>


Main.xml

?
1
2
3
4
5
6
7
8
9
<!--?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">
<edittext android:id="@+id/word"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="@string/input">
<edittext android:id="@+id/detail"android:layout_width="fill_parent"android:layout_height="wrap_content"android:lines="3"android:hint="@string/input"
<button android:id="@+id/insert"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/insert">
<edittext android:id="@+id/key"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="@string/record"
</edittext></button><button android:id="@+id/search"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/search">   
<listview android:id="@+id/show"android:layout_width="fill_parent"android:layout_height="fill_parent">           
</listview></button></edittext></edittext></linearlayout>

string.xml

?
1
2
3
4
5
6
7
8
9
<!--?xml version="1.0"encoding="utf-8"?-->
<resources>
    <string name="app_name">生词本</string>
    <string name="insert">添加生词</string>
    <string name="search">查找</string>
    <string name="detail">解释</string>
    <string name="input">请输入...</string>
    <string name="record">暂无</string>
</resources>

0 0
原创粉丝点击