您的位置:首页 > 移动开发 > Android开发

Android如何正确且简单的访问数据库

2016-09-02 17:29 344 查看
Android中数据可以保存在SQL Database中,这篇以数据库UserDictionary为例,谈谈访问数据库要注意问题。

查询

注意事项:

1. 查询是耗时操作,所以要开启一个工作线程来执行查询操作,然后在UI Thread上的ListView进行显示。第一想法是用 thread+handler(Android中内置一个类AsyncQueryTask就是这个实现),不过还需要封装下,当数据改变的时候,我们需要让ListView自动更新,所以最终Android推荐使用Loader。

2. 显示在ListView上的时候,查询的列必须包含 _id 列,否则会报错。

使用Loader好处

1、适用任何Activity和Fragment

2、提供异步加载

3、对数据源监测,数据改变了及时更新

4、配置(如屏幕方向)改变时候 ,重新连接最后 一个Loader的游标 ,不用重新查询。

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String TAG = "david";
private static final int URL_LOADER = 0;
private SimpleCursorAdapter mAdapter;
private String[] from = {UserDictionary.Words.WORD, UserDictionary.Words.LOCALE};
private int[] to = {android.R.id.text1, android.R.id.text2};
private ListView mListView;
private Uri uri = UserDictionary.Words.CONTENT_URI;
//显示在ListView中必须要有 _id 的列
String[] projection = {UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.LOCALE};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.myListView);

mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to);
mListView.setAdapter(mAdapter);
//通过Loader加载数据
getLoaderManager().initLoader(URL_LOADER, null, this);
}

@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
switch (loaderID) {
case URL_LOADER:
return new CursorLoader(MainActivity.this, uri, projection, null, null, null);
default:
return null;
}
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}


插入

插入注意事项:

1. 数据库是允许相同的数据插入的,所以我们要考虑是否要检测数据已经存在

2. 用 ContentResolver.query() 获取到Cursor后,要对Curosr进行判断 。 如果 cursor == null 说明查询失败,如果 cursor.getCount() <1 说明没有数据,可能需要重新查询(因为可能是查询条件错误), 排除这两个条件就是说明查询数据正常。

/**
* 插入数据
*/
private void insertData() {
String[] words = {"America", "中国"};
String[] locals = {"en_US", "zh_CN"};
ContentValues values = new ContentValues();
for (int i = 0; i < 2; i++) {
if (!isExists(words[i], locals[i])) {
values.put(UserDictionary.Words.WORD, words[i]);
values.put(UserDictionary.Words.LOCALE, locals[i]);
Uri rowUri = getContentResolver().insert(uri, values);
Log.d("david", "rowUri=" + rowUri);
}
}
}

/**
* 检测数据是否存在
*/
private boolean isExists(String word, String local) {
String selection = UserDictionary.Words.WORD + "=? and " + UserDictionary.Words.LOCALE + "=?";
String[] selectionArgs = {word, local};
Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (c != null && c.getCount() > 0) {
c.close();
return true;
}
return false;
}


更新

更新注意事项:

1. 下面代码中 where 和 selectionArgs为标准的写法(程序健壮性,防止恶意输入),其中"=?"问号为占位符,代表selectionArgs中的参数,上面代码中的 isExists()方法,我们可以看到有两个问号,它们就分别代表selectionArgs数组中的第一位和第二位

private void updateData() {
ContentValues values = new ContentValues();
values.put(UserDictionary.Words.LOCALE, "zh_CN");
String where = UserDictionary.Words.WORD + "=?";
String[] selectionArgs = {"America"};
int count = getContentResolver().update(uri, values, where, selectionArgs);
Log.d(TAG, "updateData: count" + count);
}


删除

private void deleteData() {
String where = UserDictionary.Words.WORD + " =?";
String[] selectionArgs = {"America"};
int count = getContentResolver().delete(uri, where, selectionArgs);
Log.d(TAG, "deleteData: count=" + count);
}


Loader用法参考:

https://developer.android.com/guide/components/loaders.html

https://developer.android.com/training/load-data-background/index.html

ContentProvider的基本用法参考

https://developer.android.com/guide/topics/providers/content-provider-basics.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 数据库 SQL