Android数据持久化篇

一.文件操作篇

主要通过流来完成

  得到输出流对象FileOutputStream:通过Context的openFileOuput("文件名",模式)方法获取

    文件路径:/data/data/<包名>/files/  存放在这个目录下
    模式有二:Activity.MODE_PRIVATE覆盖;Activity.MODE_APPEND——追加

  得到输入流对象FileInputStream:通过Context的openFileInput("文件名")返回一个输入流对象

    会自动在路径:/data/data/<包名>/files/  下找到要读取的文件名

  接下来的操作即为java的IO操作技术!

贴入一段小代码

  1 package com.example.filepersistencetest;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.BufferedWriter;
  5 import java.io.FileInputStream;
  6 import java.io.FileOutputStream;
  7 import java.io.InputStreamReader;
  8 import java.io.OutputStreamWriter;
  9 
 10 import android.app.Activity;
 11 import android.os.Bundle;
 12 import android.util.Log;
 13 import android.view.View;
 14 import android.view.View.OnClickListener;
 15 import android.widget.Button;
 16 import android.widget.EditText;
 17 
 18 public class MainActivity extends Activity implements OnClickListener {
 19     private EditText editText;
 20     private Button sava_button;
 21     private Button read_button;
 22 
 23     @Override
 24     protected void onCreate(Bundle savedInstanceState) {
 25         super.onCreate(savedInstanceState);
 26         setContentView(R.layout.activity_main);
 27         editText = (EditText) findViewById(R.id.edit);
 28         sava_button = (Button) findViewById(R.id.save);
 29         read_button = (Button) findViewById(R.id.read);
 30 
 31         // 绑定单击事件
 32         sava_button.setOnClickListener(this);
 33         read_button.setOnClickListener(this);
 34 
 35     }
 36 
 37     @Override
 38     public void onClick(View v) {
 39         // 监听
 40         switch (v.getId()) {
 41         case R.id.save:
 42             save();
 43             break;
 44         case R.id.read:
 45             read();
 46             break;
 47 
 48         default:
 49             break;
 50         }
 51 
 52     }
 53 
 54     public void save() {
 55         String inputText = editText.getText().toString();
 56         BufferedWriter bufw = null;
 57         FileOutputStream out = null;
 58         // 得到输出流 Context->openFileOutput("文件名",写出模式——覆盖Private或者追加append)
 59         // 返回FileOutputStream对象
 60         try {
 61 
 62             out = openFileOutput("my_data.txt", Activity.MODE_PRIVATE);
 63             bufw = new BufferedWriter(new OutputStreamWriter(out));
 64             bufw.write(inputText);
 65             Log.d("test", inputText);
 66             bufw.flush();
 67             editText.setText("");
 68         } catch (Exception e) {
 69             throw new RuntimeException("打开文件异常!!");
 70         } finally {
 71             try {
 72                 if (null != bufw)
 73                     bufw.close();
 74             } catch (Exception e2) {
 75                 throw new RuntimeException("关闭流失败");
 76             }
 77         }
 78     }
 79 
 80     public void read() {
 81         editText.setText("");
 82         FileInputStream in = null;
 83         BufferedReader bur = null;
 84         try {
 85             in = openFileInput("my_data.txt");
 86             bur = new BufferedReader(new InputStreamReader(in));
 87             String line = null;
 88             boolean flag = false;
 89             while ((line = bur.readLine()) != null) {
 90                 if (flag)
 91                     editText.append("
" + line);//
 92                 else {
 93                     editText.append(line);
 94                     flag=true;
 95                 }
 96             }
 97         } catch (Exception e) {
 98             // TODO: handle exception
 99         } finally {
100             try {
101                 bur.close();
102             } catch (Exception e2) {
103                 // TODO: handle exception
104             }
105         }
106 
107     }
108 
109 }
filepersistence

 另外补充两点

  a.TextUtils.isEmpty(inputText)——文本工具类,双重判空
  b.edit.setSelection(inputText.length())——设置光标到末尾

二.xml存储篇——SharedPreferences

  文件操作方式有点类似于无脑读,无脑写

  而SharedPreferences则将数据分类的比较好,可以做到存什么类型就读什么类型,以键值对的方式存储

  通常映射关系简单的时候,用SharedPreferences是比较合适的

  存储路径:/data/data/<packagename>/shared_prefs/目录下
  A.获取SharedPreferences,三种方法
  a.Context 的 getSharedPreferences("文件名",模式)——如果指定的文件不存在,则会自动创建
    MODE_PRIVATE(=0,默认,只有当前应用程序可以访问)
    MODE_MULTI_PROCESS,用于多个进程多同一个SharedPreferences进行访问
  b.Activity 的 getPreferences(模式) 会自动将当前活动的类名作为SharedPreferences文件名
  c.PreferenceManager 的 静态getDefaultSharedPreferences(Context)——自动使用当前应用程序名称作为文件名的前缀
  B.写
  a.获得编辑器 通过SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象
  b.通过编辑器写数据 putBoolean putString ==
  c.提交 commit()

代码示例:

 1         saveButton.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5                 // Context获取SharedPreferences对象,创建编辑器
 6                 SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
 7                 // put内容
 8                 editor.putString("name", "二哥");
 9                 editor.putInt("age", 22);
10                 editor.putBoolean("married", false);
11                 // 提交
12                 editor.commit();
13             }
14         });
 1         getButton.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5                 SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
 6                 String name = pref.getString("name", "null");
 7                 int age = pref.getInt("age", 0);
 8                 boolean married = pref.getBoolean("married", false);
 9                 
10                 Toast.makeText(MainActivity.this, name+"::"+age+"::"+married, Toast.LENGTH_LONG).show();
11             }
12         });

记住密码功能实现——参看BroadcastBestPractice

a.定义一个控制器ActivityController管理所有的活动:包括增加,移除活动和销毁所有活动,通过一个List承载

 1 package com.example.broadcastbestpractic;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import android.app.Activity;
 7 
 8 /**
 9  * 活动控制器
10  * 1.添加活动
11  * 2.删除活动
12  * 3.销毁所有活动
13  */
14 public class ActivityController {
15     public static List<Activity> activities = new ArrayList<Activity>();
16     public static void addActivity(Activity activity ){
17         activities.add(activity);
18     }
19     public static void removeActivity(Activity activity ){
20         
21         activities.remove(activity);
22     }
23     public static void finishAll(){
24         for(Activity activity:activities){
25             activity.finish();
26         }
27     }
28 }
ActivityController

b.定义一个基类继承Activity,改类的onCreate和onDestory方法分别实现增加和移除活动

 1 package com.example.broadcastbestpractic;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 
 6 public class BaseActivity extends Activity {
 7 
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         // TODO Auto-generated method stub
11         super.onCreate(savedInstanceState);
12         ActivityController.addActivity(this);
13     }
14 
15     @Override
16     protected void onDestroy() {
17         // TODO Auto-generated method stub
18         super.onDestroy();
19         ActivityController.removeActivity(this);
20     }
21     
22 }
BaseActivity

c.主界面MainActivity,具有Button,用于发送强制下线广播

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.broadcastbestpractic.MainActivity" >
10 
11     <Button 
12         android:id="@+id/force_offline"
13         android:layout_width="match_parent"
14         android:layout_height="wrap_content"
15         android:text="Send a force offline broadcast"
16         android:gravity="center"
17         />
18 
19 </RelativeLayout>
activity_main.xml
 1 package com.example.broadcastbestpractic;
 2 
 3 import android.app.Activity;
 4 import android.content.Intent;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.view.View.OnClickListener;
 8 import android.widget.Button;
 9 
10 
11 public class MainActivity extends Activity {
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_main);
17         
18         Button offLine_btn = (Button) findViewById(R.id.force_offline);
19         offLine_btn.setOnClickListener(new OnClickListener() {
20             
21             @Override
22             public void onClick(View v) {
23                 // 发送轻质下线广播                
24                 Intent intent = new Intent("com.example.broadcastbestpractic.FORCE_OFFLINE");
25                 
26                 sendBroadcast(intent);
27                 
28             }
29         });
30     }
31 
32 }
MainActivity

d.登录界面LoginActivity,登录成功则跳转至主界面

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:stretchColumns="1"
 6      >
 7     
 8     <TableRow >
 9         <TextView
10             android:layout_height="wrap_content"
11             android:text="Account:"
12              />
13         <EditText
14             android:id="@+id/account"
15             android:layout_height="wrap_content"
16             android:hint="admin 123456"
17              />
18     </TableRow>
19     
20     <TableRow >
21         <TextView
22             android:layout_height="wrap_content"
23             android:text="Password:"
24              />
25         <EditText
26             android:id="@+id/password"
27             android:layout_height="wrap_content"
28             android:inputType="textPassword"
29              />
30     </TableRow>
31     <TableRow >
32         <CheckBox 
33             android:id="@+id/remember_pass"
34             android:layout_height="wrap_content"
35             android:layout_gravity="right"
36             android:layout_marginRight="10dp"
37             />
38         <TextView
39             android:layout_height="wrap_content"
40             android:layout_gravity="center_vertical"
41             android:text="Remenbered password"
42              />
43     </TableRow>
44     <TableRow >
45         <Button 
46             android:id="@+id/login"
47             android:text="login"
48             android:layout_span="2"
49             />
50         
51     </TableRow>
52 
53 </TableLayout>
login.xml
 1 package com.example.broadcastbestpractic;
 2 
 3 import android.content.Intent;
 4 import android.content.SharedPreferences;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.view.View.OnClickListener;
 8 import android.widget.Button;
 9 import android.widget.CheckBox;
10 import android.widget.EditText;
11 import android.widget.Toast;
12 
13 public class LoginActivity extends BaseActivity {
14     private EditText accoutnEdit;
15     private EditText passwordEdit;
16     private Button loginButton;
17     private CheckBox rememberBox;
18 
19 
20     private SharedPreferences pref;
21     private SharedPreferences.Editor editor;
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         
26         setContentView(R.layout.login);
27         
28         loginButton = (Button) findViewById(R.id.login);
29         accoutnEdit = (EditText) findViewById(R.id.account);
30         passwordEdit = (EditText) findViewById(R.id.password);
31         rememberBox = (CheckBox) findViewById(R.id.remember_pass);
32         
33         /* 在登录界面创建的时候,先读取xml文件,看复选框的值是否为true
34          * 如果为true,复选框状态改为true,账号密码的内容设置为xml文件的账号密码
35          * 不为true,则不管
36          */
37         // 获取checkbox的值
38         pref = getSharedPreferences("data", MODE_PRIVATE);
39         Boolean isRemember = pref.getBoolean("isRemember", false);
40         
41         if(isRemember){
42             accoutnEdit.setText(pref.getString("account", ""));
43             passwordEdit.setText(pref.getString("password", ""));
44             
45             // 注意设置选中的语句为 setChecked(true)
46             rememberBox.setChecked(true);
47         }
48         
49         loginButton.setOnClickListener(new OnClickListener() {
50             
51             @Override
52             public void onClick(View v) {
53                 // 验证成功则跳转至主界面,失败者提示账号密码不正确
54                 if("admin".equals(accoutnEdit.getText().toString())&&"123456".equals(passwordEdit.getText().toString())){
55                     // 记录账号
56                     editor = getSharedPreferences("data", MODE_PRIVATE).edit();
57                     // 如果选中,则上传
58                     if(rememberBox.isChecked()){ 
59                         editor.putBoolean("isRemember", true);
60                         editor.putString("account", "admin");
61                         editor.putString("password", "123456");
62                         
63                     }else {
64                         // 如果未选中,则清除,如果不清除,依然会记住密码
65                         // 可用的方案二是,如果不清除,可以吧isRemember这个值设置为false,就不用大范围清空数据
66                         editor.clear();
67                     }
68                     editor.commit();
69                     
70                     Intent intent = new Intent(LoginActivity.this,MainActivity.class);
71                     
72                     startActivity(intent);
73                 }else {
74                     Toast.makeText(LoginActivity.this, "account or password is not corret", Toast.LENGTH_SHORT).show();
75                 }
76                 
77             }
78         });
79     }
80 }
LoginActivity

e.静态广播接收器,用于接收强制下线广播,收到后销毁所有活动,弹出AlertDialog,提示重新登录

 1 package com.example.broadcastbestpractic;
 2 
 3 import android.app.AlertDialog;
 4 import android.content.BroadcastReceiver;
 5 import android.content.Context;
 6 import android.content.DialogInterface;
 7 import android.content.DialogInterface.OnClickListener;
 8 import android.content.Intent;
 9 import android.view.WindowManager;
10 /**
11  * 
12  * 静态注册一个广播接收器,用于销毁活动和开启活动
13  */
14 public class OfflineReceiver extends BroadcastReceiver {
15 
16     @Override
17     public void onReceive(final Context context, Intent intent) {
18         // 销毁活动
19         ActivityController.finishAll();
20         // 弹出对话框
21         AlertDialog.Builder alerBuilder = new AlertDialog.Builder(context);
22         alerBuilder.setTitle("Warnning!");
23         alerBuilder.setMessage("You are forced line , plese try to login agin.");
24         alerBuilder.setCancelable(false);
25         alerBuilder.setPositiveButton("OK", new OnClickListener() {
26             
27             @Override
28             public void onClick(DialogInterface dialog, int which) {
29                 // 销毁所有活动
30                 ActivityController.finishAll();
31                 // 重启登录
32                 Intent intent = new Intent(context, LoginActivity.class);
33                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
34                 context.startActivity(intent);
35             }
36         });
37         
38         AlertDialog dialog = alerBuilder.create();
39         
40         // dialog 创建好了,必须要让其显示,并且屏蔽home键
41         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
42         dialog.show();
43         
44 
45     }
46 
47 }
OfflineReceiver

f.Manifest注册,LoginActivity(入口),MainActivity(主界面),静态广播

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.broadcastbestpractic"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6 
 7     <uses-sdk
 8         android:minSdkVersion="14"
 9         android:targetSdkVersion="19" />
10 
11     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
12 
13     <application
14         android:allowBackup="true"
15         android:icon="@drawable/ic_launcher"
16         android:label="@string/app_name"
17         android:theme="@style/AppTheme" >
18         <activity
19             android:name=".LoginActivity"
20             android:label="@string/app_name" >
21             <intent-filter>
22                 <action android:name="android.intent.action.MAIN" />
23 
24                 <category android:name="android.intent.category.LAUNCHER" />
25             </intent-filter>
26         </activity>
27         <activity android:name=".MainActivity" >
28         </activity>
29         <receiver android:name="com.example.broadcastbestpractic.OfflineReceiver">
30             <intent-filter >
31                 <action android:name="com.example.broadcastbestpractic.FORCE_OFFLINE"/>
32             </intent-filter>
33         </receiver>
34     </application>
35 
36 </manifest>
AndroidManifest.xml

注意:

  a.Receiver中弹出对话框的步骤以及需要的权限
  b.Manifest中要声明权限 android.permission.SYSTEM_ALERT_WINDOW,因为需要对话框一直存活直到点击重新ok重新登录

三.sqlite数据库篇

首先得知道的事情:

1.当数据映射复杂的时候,必然会用到数据库

2.Android内置轻量级数据库sqlite,路径在/system/xbin/sqlite3

3.程序中创建的数据库地址:/data/data/<包名>/databases/目录下

4.用实现抽象类SQLiteOpenHelper的子类对象XXX来创建和升级数据库

5.用XXX.getReadableDatabase()或XXX.getWritableDatabase()获取SQLiteDatabase对象YYY

6.通过YYY进行数据的增删改查

补充下cmd下sqlite测试操作

C:Usersjoho>adb shell

 $ su

 # cd /data/data/com.example.databasetest/databases

 # sqlite3 BookStore.db

 sqlite>.table

 sqlite>.schema

 sqlite>select * from Book;

 sqlite>.quit

 ... 

1.创建数据库

23.sqLiteOpenHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
38.sqLiteOpenHelper.getWritableDatabase();

2.增

 1         addDataButton.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5                 // SQLiteOpenHelper的getWritableDatabase和getReadableDatab会返回一个SQLiteDatabase对象
 6                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 7 //                public long insert(String table, String nullColumnHack, ContentValues values)
 8                 ContentValues values = new ContentValues();
 9                 values.put("author", "erge");
10                 values.put("price", "88.8");
11                 values.put("pages", "1");
12                 values.put("name", "程序员的自我修养");
13                 db.insert("Book", null, values);// 插入一条数据
14                 
15                 values.clear();  // 准备插入第二条
16                 values.put("author", "erge");
17                 values.put("price", "888.8");
18                 values.put("pages", "2");
19                 values.put("name", "程序员的未来");
20                 db.insert("Book", null, values); //插入第二条
21                 
22             }
23         });

3.改

 1         updateButton.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5                 // TODO Auto-generated method stub
 6                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 7 //                 public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
 8 //                (表名,值,where,where的值)
 9                 ContentValues values = new ContentValues();
10                 values.put("name", "the self_improvement of developer");
11                 db.update("Book", values, "name = ?", new String[]{"程序员的自我修养"});
12                 
13                 values.clear();
14                 values.put("name", "the future of developer");
15                 db.update("Book", values, "name = ?", new String[]{"程序员的未来"});
16                 Toast.makeText(MainActivity.this, "update sucess", Toast.LENGTH_SHORT).show();
17             }
18         });

4.删

 1         deleteButton.setOnClickListener(new OnClickListener() {
 2             
 3             @Override
 4             public void onClick(View v) {
 5                 // 
 6                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 7 //                public int delete(String table, String whereClause, String[] whereArgs)
 8                 db.delete("Book", "pages > ?", new String[]{"1"});
 9             }
10         });

5.查

 1         // 查询最为复杂,参数较多,得到的结果保存在游标——Cursor对象中
 2         queryButton.setOnClickListener(new OnClickListener() {
 3             
 4             @Override
 5             public void onClick(View v) {
 6                 // TODO Auto-generated method stub
 7                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 8 //                public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy) 
 9                 //columns用于约束查询哪几列,不指定则查全部
10                 //selection,selectionArgs用来约束查询哪些行,不指定则全部;
11                 //groupBy指定需要group by的列,不指定则对结果进行group by处理;
12                 //having用于对之前group by的数据进一步过滤,不指定则不过滤;orderBy对结果进行排序,不指定则默认排序
13                 
14                 // 遍历得结果会存储到一个Course对象中,通过遍历这个对象,来输出数据
15                 Cursor cursor = db.query("Book",null,null,null,null,null,null);
16                 if(cursor.moveToFirst()){
17                     do {
18                         String author = cursor.getString(cursor.getColumnIndex("author"));
19                         Double price = cursor.getDouble(cursor.getColumnIndex("price"));
20                         int pages = cursor.getInt(cursor.getColumnIndex("pages"));
21                         String name = cursor.getString(cursor.getColumnIndex("name"));
22                         Log.d("test", "name::"+name);
23                         Log.d("test", "pages::"+pages);
24                         Log.d("test", "price::"+price);
25                         Log.d("test", "author::"+author);
26                     } while (cursor.moveToNext());
27                 }
28                 cursor.close();
29             }
30         });

DatabaseTest代码

主布局

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6 
 7     <Button 
 8         android:id="@+id/create"
 9         android:layout_height="wrap_content"
10         android:layout_width="match_parent"
11         android:text="create database BookStore.db"
12         />
13 
14     <Button 
15         android:id="@+id/add_data"
16         android:layout_height="wrap_content"
17         android:layout_width="match_parent"
18         android:text="Add data"
19         />
20     <Button 
21         android:id="@+id/update_data"
22         android:layout_height="wrap_content"
23         android:layout_width="match_parent"
24         android:text="Update data"
25         />
26     <Button 
27         android:id="@+id/delete_data"
28         android:layout_height="wrap_content"
29         android:layout_width="match_parent"
30         android:text="Delete data"
31         />
32     <Button 
33         android:id="@+id/query_data"
34         android:layout_height="wrap_content"
35         android:layout_width="match_parent"
36         android:text="Query data"
37         />
38     <Button 
39         android:id="@+id/replace_data"
40         android:layout_height="wrap_content"
41         android:layout_width="match_parent"
42         android:text="use transaction to replace Book"
43         />
44     
45     <Button 
46         android:id="@+id/upgrade_one"
47         android:layout_height="wrap_content"
48         android:layout_width="match_parent"
49         android:text="upgrade database one"
50         />
51     <Button 
52         android:id="@+id/upgrade_two"
53         android:layout_height="wrap_content"
54         android:layout_width="match_parent"
55         android:text="upgrade database two"
56         />
57 </LinearLayout>
activity_main.xml

定义MyDatabaseHelper继承SQLiteOpenHelper

特别注意升级数据库的写法!!

 1 package com.example.databasetest;
 2 
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 6 import android.database.sqlite.SQLiteOpenHelper;
 7 import android.widget.Toast;
 8 /**
 9  * 
10  * 注意 id 设为主键时 primary key 两个词,分开的
11  */
12 public class MyDatabaseHelper extends SQLiteOpenHelper {
13     public static final String CREATE_BOOK =
14             "create table Book(" +
15             "id integer primary key autoincrement," +
16             "author text, " +
17             "price real," +
18             "pages integer," +
19             "name text)";
20     public static final String CREATE_CATEGORY="create table Category(" +
21             "id integer primary key autoincrement," +
22             "category_name text," +
23             "category_code integer)";
24     private Context mContext;//为什么需要?获取SQLiteOpenHelper实例的时候,会传入context,为了在这个context中进行操作
25 //  构造方法(contex , 数据库名 , 光标? , 版本号)
26     public MyDatabaseHelper(Context context, String name,
27             CursorFactory factory, int version) {
28         super(context, name, factory, version);
29         mContext = context;
30     }
31 
32     @Override
33     public void onCreate(SQLiteDatabase db) {
34         // 创建数据库的时候创建一张表
35         db.execSQL(CREATE_BOOK);
36         //db.execSQL(CREATE_CATEGORY);
37         Toast.makeText(mContext, "create table sussessed", Toast.LENGTH_SHORT).show();
38     }
39 
40     @Override
41     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
42         // 更新数据库——感觉这种方法很糟糕,如果存在则删除,数据不要了??
43         /*
44         db.execSQL("drop table if exists Category");
45         db.execSQL("drop table if exists Book");
46         onCreate(db);
47         */
48         
49         // 最佳写法——当然第二版创建时就会创建category表,第三版创建时就会增加id
50         // 只有低版本升级是才会执行到下面的语句,另外特别注意:
51         // 这里并没有写break语句,是为了保证夸版本升级可以执行到所有语句——感觉还能改造,事务之类的
52         switch (oldVersion) {
53         //升级至第二版时,会多创建一个category表
54         case 1:
55             db.execSQL(CREATE_CATEGORY);
56         //升级至第三版时,Book表会新建一列 category_id
57         case 2:
58             db.execSQL("alter table Book add column category_id integer");
59         default:
60         }
61         
62     }
63 
64 }
MyDatabaseHelper

主入口

  1 package com.example.databasetest;
  2 
  3 import android.app.Activity;
  4 import android.content.ContentValues;
  5 import android.database.Cursor;
  6 import android.database.sqlite.SQLiteDatabase;
  7 import android.database.sqlite.SQLiteOpenHelper;
  8 import android.os.Bundle;
  9 import android.util.Log;
 10 import android.view.View;
 11 import android.view.View.OnClickListener;
 12 import android.widget.Button;
 13 import android.widget.Toast;
 14 
 15 
 16 public class MainActivity extends Activity {
 17     private SQLiteOpenHelper sqLiteOpenHelper;
 18     @Override
 19     protected void onCreate(Bundle savedInstanceState) {
 20         super.onCreate(savedInstanceState);
 21         setContentView(R.layout.activity_main);
 22         // 得到SQLiteOpentHelper的实例
 23         sqLiteOpenHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
 24         Button createDatabaseButton = (Button) findViewById(R.id.create);
 25         Button addDataButton = (Button) findViewById(R.id.add_data);
 26         Button updateButton = (Button) findViewById(R.id.update_data);
 27         Button deleteButton = (Button) findViewById(R.id.delete_data);
 28         Button queryButton = (Button) findViewById(R.id.query_data);
 29         Button replaceButton = (Button) findViewById(R.id.replace_data);
 30         Button upgrade_One_Button = (Button) findViewById(R.id.upgrade_one);
 31         Button upgrade_Two_Button = (Button) findViewById(R.id.upgrade_two);
 32         
 33         createDatabaseButton.setOnClickListener(new OnClickListener() {
 34             
 35             @Override
 36             public void onClick(View v) {
 37                 // 没有则会创建数据库,有则不创建
 38                 sqLiteOpenHelper.getWritableDatabase();
 39             }
 40         });
 41         
 42 
 43         addDataButton.setOnClickListener(new OnClickListener() {
 44             
 45             @Override
 46             public void onClick(View v) {
 47                 // SQLiteOpenHelper的getWritableDatabase和getReadableDatab会返回一个SQLiteDatabase对象
 48                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 49 //                public long insert(String table, String nullColumnHack, ContentValues values)
 50                 ContentValues values = new ContentValues();
 51                 values.put("author", "erge");
 52                 values.put("price", "88.8");
 53                 values.put("pages", "1");
 54                 values.put("name", "程序员的自我修养");
 55                 db.insert("Book", null, values);// 插入一条数据
 56                 
 57                 values.clear();  // 准备插入第二条
 58                 values.put("author", "erge");
 59                 values.put("price", "888.8");
 60                 values.put("pages", "2");
 61                 values.put("name", "程序员的未来");
 62                 db.insert("Book", null, values); //插入第二条
 63                 
 64             }
 65         });
 66         
 67         updateButton.setOnClickListener(new OnClickListener() {
 68             
 69             @Override
 70             public void onClick(View v) {
 71                 // TODO Auto-generated method stub
 72                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 73 //                 public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
 74 //                (表名,值,where,where的值)
 75                 ContentValues values = new ContentValues();
 76                 values.put("name", "the self_improvement of developer");
 77                 db.update("Book", values, "name = ?", new String[]{"程序员的自我修养"});
 78                 
 79                 values.clear();
 80                 values.put("name", "the future of developer");
 81                 db.update("Book", values, "name = ?", new String[]{"程序员的未来"});
 82                 Toast.makeText(MainActivity.this, "update sucess", Toast.LENGTH_SHORT).show();
 83             }
 84         });
 85         
 86         deleteButton.setOnClickListener(new OnClickListener() {
 87             
 88             @Override
 89             public void onClick(View v) {
 90                 // 
 91                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
 92 //                public int delete(String table, String whereClause, String[] whereArgs)
 93                 db.delete("Book", "pages > ?", new String[]{"1"});
 94             }
 95         });
 96         
 97         // 查询最为复杂,参数较多
 98         queryButton.setOnClickListener(new OnClickListener() {
 99             
100             @Override
101             public void onClick(View v) {
102                 // TODO Auto-generated method stub
103                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
104 //                public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy) 
105                 //columns用于约束查询哪几列,不指定则查全部
106                 //selection,selectionArgs用来约束查询哪些行,不指定则全部;
107                 //groupBy指定需要group by的列,不指定则对结果进行group by处理;
108                 //having用于对之前group by的数据进一步过滤,不指定则不过滤;orderBy对结果进行排序,不指定则默认排序
109                 
110                 // 遍历得结果会存储到一个Course对象中,通过遍历这个对象,来输出数据
111                 Cursor cursor = db.query("Book",null,null,null,null,null,null);
112                 if(cursor.moveToFirst()){
113                     do {
114                         String author = cursor.getString(cursor.getColumnIndex("author"));
115                         Double price = cursor.getDouble(cursor.getColumnIndex("price"));
116                         int pages = cursor.getInt(cursor.getColumnIndex("pages"));
117                         String name = cursor.getString(cursor.getColumnIndex("name"));
118                         Log.d("test", "name::"+name);
119                         Log.d("test", "pages::"+pages);
120                         Log.d("test", "price::"+price);
121                         Log.d("test", "author::"+author);
122                     } while (cursor.moveToNext());
123                 }
124                 cursor.close();
125             }
126         });
127         
128         replaceButton.setOnClickListener(new OnClickListener() {
129             
130             @Override
131             public void onClick(View v) {
132                 // TODO Auto-generated method stub
133                 SQLiteDatabase db = sqLiteOpenHelper.getWritableDatabase();
134                 db.beginTransaction();
135                 try {
136                     // 删除原来的表
137                     db.delete("Book", null, null);
138                     
139                     // 中断测试
140                     if(true){
141                         throw new RuntimeException("...");
142                     }
143                     // 重新添加数据
144                     ContentValues values = new ContentValues();
145                     values.put("author", "nima");
146                     values.put("price", 25.5);
147                     values.put("pages", 88);
148                     values.put("name", "zhiqinchun");
149                     
150                     db.insert("Book", null, values);
151                     db.setTransactionSuccessful();
152                 } catch (Exception e) {
153                     // TODO: handle exception
154                 }finally{
155                     db.endTransaction();
156                 }
157             }
158         });
159         
160         upgrade_One_Button.setOnClickListener(new OnClickListener() {
161             
162             @Override
163             public void onClick(View v) {
164                 // 这里数据库版本应该搞个变量控制一下,不然升级就只能升级一次  ,后面指定的版本号比之前的大的话,就会调用onUpgrade方法
165                 sqLiteOpenHelper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 2);
166                 sqLiteOpenHelper.getWritableDatabase();
167                 
168             }
169         });
170         upgrade_Two_Button.setOnClickListener(new OnClickListener() {
171             
172             @Override
173             public void onClick(View v) {
174                 // 这里数据库版本应该搞个变量控制一下,不然升级就只能升级一次  ,后面指定的版本号比之前的大的话,就会调用onUpgrade方法
175                 sqLiteOpenHelper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null, 3);
176                 sqLiteOpenHelper.getWritableDatabase();
177                 
178             }
179         });
180         
181     }
182 
183 }
MainActivity
原文地址:https://www.cnblogs.com/erhai/p/4910628.html