Android专题6——学习SQLite, ListView 和 Content provider小结

 

如何自动创建数据库?

  • 有相关的工具类吗?  SQLiteOpenHelper

  • 如果有,是如何实现自动创建的?

 

 

 

如何使用SQLiteOpenHelper?

  • 关于SQLiteOpenHelper

  1. 它是一个抽象类
  2. 自定义的DatabaseHelper类最好放在service包中
  • 创建的数据库的存储位置

  Data--> Data--> 应用所在包

 1 package com.njulya.databasedemo_service;
 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 
 8 public class DatabaseHelper extends SQLiteOpenHelper {
 9 
10     public DatabaseHelper(Context context) {
11         //数据库的名字:databasedemo.db 必须加后缀
12         //该数据库在第一次调用DatabaseHelper实例的
13         //getReadableDatabase或getWritable方法时被创建 
14         super(context, "databasedemo.db", null, 1);
15     }
16 
17     @Override
18     public void onCreate(SQLiteDatabase db) {
19         //该方法在创建DatabaseHelper实例时被调用
20         //多用于完成数据库中数据表的创建
21         db.execSQL("CREATE TABLE person(_id integer primary key autoincrement, " +
22                 "name varchar(20), phone varchar(20), account integer )");
23     }
24 
25     @Override
26     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
27         //当version发生改变时调用该方法
28         //当数据库中发生变化,如数据表希望增加新列时,可以改变version号,从而调用该方法,完成改变数据库
29     }
30 
31 }

 

 

 

如何操作SQLiteDatabase?

  • 包及目录结构安排

  1. 可以将数据表中的每条数据定义为一个javabean,最好放在domain包下
  2. 将对应的业务bean放在service包下

 

  • 向数据库中添加数据

 1     public void save(Person person){
 2         //创建DatabaseHelper实例对象,调用getWritableDatabase得到db对象
 3         SQLiteDatabase db = dbhelper.getWritableDatabase();
 4         //执行SQL语句
 5 //        db.execSQL("insert into person(name, phone, account) values(?, ?, ?) ",
 6 //                new String[]{person.getName(), person.getPhone(), String.valueOf(person.getAccount())});
 7         
 8         //也可以利用SQLiteDatabase 提供的API接口
 9         ContentValues values = new ContentValues();
10         values.put("name", "zhangyang");
11         values.put("phone", "1345068459");
12         values.put("account", 100);
13         db.insertOrThrow("person", null, values);
14         db.close();
15     }
  • 删除数据库中数据

 1     /**
 2      * 按照指定_id删除数据
 3      * @param _id
 4      */
 5     public void delete(int _id){
 6         SQLiteDatabase db = dbhelper.getWritableDatabase();
 7         //SQL:delete from person where _id=?, ?=_id;
 8 //        db.execSQL("delete from person where _id="+ _id );
 9         //whereClause对应 删除条件 whereArgs对应占位符?的参数
10         db.delete("person", "_id=?", new String[]{String.valueOf(_id)});
11     }
  • 更新数据库中的数据

 1     /**
 2      * 更新指定id的数据
 3      * @param person
 4      */
 5     public void update(Person person){
 6         SQLiteDatabase db = dbhelper.getWritableDatabase();
 7         ContentValues values = new ContentValues();
 8         values.put("name", person.getName());
 9         values.put("phone", person.getPhone());
10         values.put("account", person.getAccount());
11         //SQL update person set name=?,phone=?,account=? where _id=?, new Object[]{person.getName()....}
12         db.update("person", values, "_id=?", new String[]{String.valueOf(person.get_id())});
13     }
  • 数据库查找

  1. *代表所有字段, #代表数字, ?占位符
  2. count(*) 可以统计所有的行数,包括为null的行 count(1) 统计的是第一个子字段的行数,为null的行数 不统计。 sql 语句中 有时候1 代表对应的 第一个字段,第二个字段 一次类推
  3. order by asc(升序)/desc (降序)
  4. select */count(*)from person order by ? asc limit ?,?
 1     /**
 2      * 查找指定id对应的数据
 3      * SQL: select * from person where id=?  
 4      * @param _id
 5      * @return
 6      */
 7     public Person find(int _id){
 8         SQLiteDatabase db = dbhelper.getReadableDatabase();
 9 //        Cursor cursor = db.rawQuery("select * from person where _id=?"
10 //                , new String[]{String.valueOf(_id)});
11         Cursor cursor = db.query("person", null, "_id=?", new String[]{String.valueOf(_id)}, null, null, null);
12         if(cursor.moveToFirst()){
13             String name = cursor.getString(cursor.getColumnIndex("name"));
14             String phone = cursor.getString(cursor.getColumnIndex("phone"));
15             int account = cursor.getInt(cursor.getColumnIndex("account"));
16             return new Person(name, phone, account);
17         }
18         return null;
19     }
20     /**
21      * select * from person order by _id asc limit ?,?
22      * @param offset
23      * @param maxItems
24      * @return
25      */
26     public Cursor getScrollDate(int offset, int maxItems){
27         SQLiteDatabase db = dbhelper.getReadableDatabase();
28         Cursor cursor = db.query("person", null, null, null, null, null,
29                 "_id asc", String.valueOf(offset)+","+String.valueOf(maxItems));
30         return cursor;
31     }
32     /**
33      * select count(*) from person
34      * @return
35      */
36     public long getCount(){
37         long result=0;
38         SQLiteDatabase db = dbhelper.getReadableDatabase();
39         Cursor cursor = db.query("person",new String[]{"count(*)"}, null, null, null, null, null);
40         if(cursor.moveToFirst()){
41             result = cursor.getLong(0);
42         }
43         return result;
44     }

 

关于Content Provider

  • Content provider 和 Activity相似,都需要在Manifest中组册,继承Content Provider

  1. android:authorities 域名, 用于唯一标识这个Content Provider
  2. 需要提供访问权限设置(如: android:exported=“true”)
  3. 自定义自己的Content Provider,同样放在应用主包下
  • Content 涉及到URI,用于唯一标识,需要使用一些相关工具类(如Uri, UriMatcher, ContentUris)

  1. Uri的parse()方法
  2. UriMatcher 的实例对象可以帮助进行URI匹配验证
  3. ContentUris的withAppendedId()方法和parseId()方法
  4. 根据需要重写相关方法
  • 作用是对外共享数据,并且提供一致的数据接口

 1 package com.njulya.databasedemo;
 2 
 3 import java.sql.SQLData;
 4 
 5 import com.njulya.databasedemo_service.DatabaseHelper;
 6 
 7 import android.content.ContentProvider;
 8 import android.content.ContentUris;
 9 import android.content.ContentValues;
10 import android.content.UriMatcher;
11 import android.database.Cursor;
12 import android.database.sqlite.SQLiteDatabase;
13 import android.net.Uri;
14 
15 public class PersonContentProvider extends ContentProvider {
16     DatabaseHelper helper;
17     public static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
18     public static final int  PERSONS = 1;
19     public static final int  PERSON = 2;
20     static{
21         //定义合法的访问路径
22         MATCHER.addURI("com.njulya.providers.personsprovider", "person", PERSONS);
23         MATCHER.addURI("com.njulya.providers.personsprovider", "person/#", PERSON);
24     }
25     
26     @Override
27     public int delete(Uri uri, String selection, String[] selectionArgs) {
28         return 0;
29     }
30     @Override
31     public String getType(Uri uri) {
32         return null;
33     }
34     @Override
35     public Uri insert(Uri uri, ContentValues values) {
36         SQLiteDatabase db = helper.getWritableDatabase();
37         switch (MATCHER.match(uri)) {
38         case PERSONS:
39             long rowid = db.insert("person", null, values);
40 //            Uri insertUri = Uri.parse("content://com.njulya.providers.personsprovider/"+rowid);
41             Uri insertUri = ContentUris.withAppendedId(uri, rowid);
42             return insertUri;
43         default:
44             throw new IllegalArgumentException("参数有误");
45         }
46 
47     }
48     @Override
49     public boolean onCreate() {
50         helper = new DatabaseHelper(getContext());
51         
52         return true;
53     }
54     @Override
55     public Cursor query(Uri uri, String[] projection, String selection,
56             String[] selectionArgs, String sortOrder) {
57         return null;
58     }
59     @Override
60     public int update(Uri uri, ContentValues values, String selection,
61             String[] selectionArgs) {
62         return 0;
63     }
64 
65 }
View Code

 

  • 插入方法

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = helper.getWritableDatabase();
        Cursor cursor;
        switch (MATCHER.match(uri)) {
        case PERSONS:
            cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder);
            return cursor;
        case PERSON:
            long rowid = ContentUris.parseId(uri);
            String where = "_id=" + rowid;
            if(selection!=null && !("".equals(where))){
                where += "and" + selection;
            }
            cursor = db.query("person", projection, where, selectionArgs, null, null, sortOrder);
            return cursor;
        default:
            throw new IllegalArgumentException("参数有误");
        }
    }

 

  • 得到返回类型

 1     @Override
 2     public String getType(Uri uri) {
 3         switch (MATCHER.match(uri)) {
 4         case PERSONS:
 5             return "vnd.android.cursor.dir/person";
 6         case PERSON:
 7             return "vnd.android.cursor.item/person";
 8         default:
 9             throw new IllegalArgumentException("参数有误");
10         }
11     }

 

监听Content Provider中的数据变化

  • Content Provider如何在数据发生变化是发出通知?

 1     @Override
 2     public Uri insert(Uri uri, ContentValues values) {
 3         SQLiteDatabase db = helper.getWritableDatabase();
 4         switch (MATCHER.match(uri)) {
 5         case PERSONS:
 6             long rowid = db.insert("person", null, values);
 7 //            Uri insertUri = Uri.parse("content://com.njulya.providers.personsprovider/"+rowid);
 8             Uri insertUri = ContentUris.withAppendedId(uri, rowid);
 9             /**
10              * 如果插入数据,PersonContentProvider会发出数据变化通知
11              * 
12              */
13             ContentResolver resolver = getContext().getContentResolver();
14             resolver.notifyChange(Uri.parse("content://com.njulya.providers.personsprovider/person"),
15                     null);
16             
17             return insertUri;
18         default:
19             throw new IllegalArgumentException("参数有误");
20         }
21 
22     }
  • 如何设置变化的观察者

 1     protected void onCreate(Bundle savedInstanceState) {
 2         super.onCreate(savedInstanceState);
 3         setContentView(R.layout.activity_main);
 4         name = (TextView)findViewById(R.id.name);
 5         phone = (TextView)findViewById(R.id.phone);
 6         account = (TextView)findViewById(R.id.account);
 7         Uri uri = Uri.parse("content://com.njulya.providers.personsprovider/person");
 8         this.getContentResolver().registerContentObserver(uri, true, new PersonContentObserver(new Handler()));
 9     }
10 
11     private class PersonContentObserver extends ContentObserver{
12 
13         public PersonContentObserver(Handler handler) {
14             super(handler);
15         }
16 
17         @Override
18         public void onChange(boolean selfChange) {
19             Uri uri = Uri.parse("content://com.njulya.providers.personsprovider/person");
20 //            //select * from person order by _id desc limit 1
21             Cursor cursor = MainActivity.this.getContentResolver().query(uri, null, null, null, "_id desc");
22             if(cursor.moveToFirst()){
23                 String mname = cursor.getString(cursor.getColumnIndex("name"));
24                 String mphone = cursor.getString(cursor.getColumnIndex("phone"));
25                 String maccount = cursor.getString(cursor.getColumnIndex("account"));
26                 name.setText(mname);
27                 phone.setText(mphone);
28                 account.setText(maccount);
29                 
30             }else{
31                 Log.d("mytest", "bad");
32             }
33         }
34         
35     }

 

posted @ 2015-01-14 16:08  lya_nju  阅读(258)  评论(0)    收藏  举报