学习笔记(五)SQLite与ContentProvider
SQLiteSQLite是Android系统内置的轻量级关系数据库,它具有运算速度快,占用资源少等优点,通常只需要几百K的内存就足够了,因此特别适合在移动设备上使用。SQLite不仅支持标准的SQL语法,还遵循数据库的ACID事务,所以用过关系型数据库的同学很容易上手SQLite; 创建数据库android为方便我们管理数据库,专门提供了SQLiteOpenHelper类,借助这个类可以非常简单的对数据库进行创建和升级;但是这个类是抽象类,我们需要自己创建一个新的类去继承它,我们需要重写onCreate()和onUpdate()方法;其次,还有两个非常重要的实例方法: public SQLiteOpenHelper(Context context,String name,CursorFactory factory,int version)
eg:我们新建一个项目创建一个名为test_database.db数据库 public class DataBasehelper extends SQLiteOpenHelper {
private static final String CREATE_DB_ONR="create table users ("
+"id integer primary key autoincrement,"
+"username text,"
+"password text"
+")";
private Context mcontext;
public DataBasehelper(Context context,int version,String database_name) {
super(context,database_name,null,version);
mcontext=context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_ONR);
Toast.makeText(mcontext,"User_DB Succeed",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) {//当新的versio大于oldversion时候,会执行该方法
}
}
Mainactivity.class public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public static final String TEST_DATABASE_DB = "test_database.db";
private SQLiteDatabase sqLiteDatabase;
private ContentValues contentValues;
private int result;
private static final String username_column="username";
private static final String password_column= "password";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_create= (Button) findViewById(R.id.btn_add_database);
btn_create.setOnClickListener(this);
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_add_database://创建数据库
DataBasehelper dataBasehelper=new DataBasehelper(this,1,TEST_DATABASE_DB);
sqLiteDatabase = dataBasehelper.getWritableDatabase();
break;
}
}
}
我们把建表语句定义成了一个字符串常量,然后再onCreate()方法中调用了exeSQL()方法去执行这条语句。这样数据库就建立成功了! 升级数据库升级数据库需要执行onUpdate()方法,只要传入一个比原来version大的数,就会执行该方法: DataBasehelper dataBasehelper2= new DataBasehelper(this,2,TEST_DATABASE_DB);
sqLiteDatabase = dataBasehelper2.getWritableDatabase();
我们version传入2,比原来的version=1要大,这时就会自动执行onUpdate()方法中的相关操作。 添加数据向数据库的表中添加数据,需要SQLiteDatabase的insert()方法; public long insert(String table,String nullColumnHack,ContentValues values) {
try {
return insertWithOnConflict(table,nullColumnHack,values,CONFLICT_NONE);
} catch (SQLException e) {
Log.e(TAG,"Error inserting " + values,e);
return -1;
}
}
table:是表名,向哪张表添加数据; contentValues.put(username_column,"two");
contentValues.put(password_column,"12345678");
contentValues.put(age_column,20);
long result01=sqLiteDatabase.insert("users",null,contentValues);
if(result01!=-1)
Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
break;
由于insert()方法返回一个long型值,如果加入出错,会返回-1;否则返回新加入行的id值; 更新数据SQLiteDatabase提供了update()方法对数据进行更新; public int update(String table,ContentValues values,String whereClause,String[] whereArgs) { return updateWithOnConflict(table,values,whereClause,whereArgs,CONFLICT_NONE);
}
第一和第二个参数上面已经提到了,第三和第四参数用于去约束更新某一行或某几行的数据,不指定的话就默认更新所有行。 contentValues.put(password_column,"112233");
result=sqLiteDatabase.update("users",contentValues,"username=?",new String[]{"two"});
if(result!=0)
Toast.makeText(this,"修改成功",Toast.LENGTH_SHORT).show();
update()返回受影响的行数,以此来判断更新是否成功。 删除数据删除数据就是要调用SQLiteDatabase的delete()方法了,其实和上面很相似: public int delete(String table,String whereClause,String[] whereArgs) {}
和update()方法参数相同; result = sqLiteDatabase.delete("users",new String[]{"two"});
if(result==1)
Toast.makeText(this,"删除成功",Toast.LENGTH_SHORT).show();
以上是删除username=“two”的用户; 查询数据SQLiteDatabase的query()方法用于对数据进行查询,这个方法的参数非常复杂: public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit) {}
Cursor cursor=sqLiteDatabase.query("users",null,null);//返回一个查询数据的集合
if(cursor.moveToFirst()){
do{ //遍历cursor对象,取出相关数据
String username=cursor.getString(cursor.getColumnIndex(username_column));
String password=cursor.getString(cursor.getColumnIndex(password_column));
Log.i("TAG",username);
Log.i("TAG",password);
}while (cursor.moveToNext());
}
cursor.close();
以上就是查询users表中的所有数据; 使用事务事务就是说某个操作结果只有成功和失败,不存在完成一半;现实中比如说银行转款,收款方和借款方银行卡金额的改变是一起完成的,中间一方有问题都不可能完成这个过程。 eg:代码示例: sqLiteDatabase.beginTransaction();//开启事务
try{
sqLiteDatabase.delete("users",null,null);
if(true){
//在这里抛出异常,检查事务的特性,即没有完成就不会删除原来的数据库
// throw new NullPointerException("检查事务的特性");
}
contentValues = new ContentValues();
contentValues.put(username_column,"one");
contentValues.put(password_column,"22222");
sqLiteDatabase.insert("users",contentValues);
contentValues.clear();//将上一个里的数据移除
contentValues.put(username_column,"two");
contentValues.put(password_column,"22222");
result01=sqLiteDatabase.insert("users",contentValues);
sqLiteDatabase.setTransactionSuccessful();//事务执行成功
if(result01!=-1)
Toast.makeText(this,"事务成功",Toast.LENGTH_SHORT).show();
}
catch (Exception e){
e.printStackTrace();
}
finally {
{
sqLiteDatabase.endTransaction();//结束事务
}
}
我们可以用抛出异常来检验事务的特性,抛出异常就不会这个过程就不会成功,不抛出就会成功执行。 ContentProviderContentProvider主要用于不同应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个应用程序中的数据,可以保证被访数据的安全性。 若要访问ContentProvider中的共享数据,要借助ContentResolve类,可以通过Context中的getContentResolver()方法获得该类的实例; URI由3个部分组成, scheme为:content:// UriMatcher类:匹配并解析Uri,并从Uri中获取数据 //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.pc.provider/users路径,返回匹配码为1
sMatcher.addURI("com.pc.provider","users",1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://com.pc.provider/users/230路径,返回匹配码为2
sMatcher.addURI("com.pc.provider","users/#",2);//#号为通配符
switch (sMatcher.match(Uri.parse("content://com.pc.provider/users/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}
ContentProvider共享数据继承时需要被重写的方法: 操作ContentProvider中的数据当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 eg:下面就用ContentProvider来读取联系人中的信息 public class Read_Context extends Activity{
private ListView listView;
private List<String> list;
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_read_context);
listView = (ListView) findViewById(R.id.context_list);
list = new ArrayList<String>();
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list);
listView.setAdapter(adapter);
readContacts();
}
private void readContacts() {
Cursor cursor=null;
try{
cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null);
while (cursor.moveToNext()){
//获取联系人名称
String name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人电话号码
String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
list.add(name+"n"+number);
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
if(cursor!=null)
cursor.close();
}
}
}
layout_read_context.xml <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<ListView android:id="@+id/context_list" android:layout_width="match_parent" android:layout_height="match_parent"></ListView>
</LinearLayout>
在AndroidManifest.xml中添加读取联系人权限: <uses-permission android:name="android.permission.READ_CONTACTS"/>
在运行之前,在首先确保联系人中有相应的数据,没有的话要新建两个联系人; 当然我们还可以创建自己的内容提供器,只需要获取应用程序内容的Uri,然后借助ContentResolver进行相关操作即可,和上面的操作大同小异。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- play 传值 Scope flash,params,renderArgs,routeArgs,s
- ruby-on-rails – Rails 3:可选has_one关联的范围
- Postgresql枚举和Java枚举之间的Hibernate映射
- C语言中设置用户识别码的相关函数的简单讲解
- Object-Oriented Design Heuristics(OOD启思录)值得一看!
- ruby-on-rails – 如何在Ruby / Rails中匹配和替换模板标签
- Invalid Host header
- 生成sqlite3.lib for bcb/vc
- flex弹出窗口的方式有几种
- 自定义圆形控件RoundImageView并认识一下attr.xml