Android专题6——学习SQLite, ListView 和 Content provider小结
如何自动创建数据库?
-
有相关的工具类吗? SQLiteOpenHelper
-
如果有,是如何实现自动创建的?
如何使用SQLiteOpenHelper?
-
关于SQLiteOpenHelper
- 它是一个抽象类
- 自定义的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?
-
包及目录结构安排
- 可以将数据表中的每条数据定义为一个javabean,最好放在domain包下
- 将对应的业务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 }
-
数据库查找
- *代表所有字段, #代表数字, ?占位符
- count(*) 可以统计所有的行数,包括为null的行 count(1) 统计的是第一个子字段的行数,为null的行数 不统计。 sql 语句中 有时候1 代表对应的 第一个字段,第二个字段 一次类推
- order by asc(升序)/desc (降序)
- 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
- android:authorities 域名, 用于唯一标识这个Content Provider
- 需要提供访问权限设置(如: android:exported=“true”)
- 自定义自己的Content Provider,同样放在应用主包下
-
Content 涉及到URI,用于唯一标识,需要使用一些相关工具类(如Uri, UriMatcher, ContentUris)
- Uri的parse()方法
- UriMatcher 的实例对象可以帮助进行URI匹配验证
- ContentUris的withAppendedId()方法和parseId()方法
- 根据需要重写相关方法
-
作用是对外共享数据,并且提供一致的数据接口
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 }
-
插入方法
@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 }

浙公网安备 33010602011771号