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的游标 ,不用重新查询。
1. 数据库是允许相同的数据插入的,所以我们要考虑是否要检测数据已经存在
2. 用 ContentResolver.query() 获取到Cursor后,要对Curosr进行判断 。 如果 cursor == null 说明查询失败,如果 cursor.getCount() <1 说明没有数据,可能需要重新查询(因为可能是查询条件错误), 排除这两个条件就是说明查询数据正常。
1. 下面代码中 where 和 selectionArgs为标准的写法(程序健壮性,防止恶意输入),其中"=?"问号为占位符,代表selectionArgs中的参数,上面代码中的 isExists()方法,我们可以看到有两个问号,它们就分别代表selectionArgs数组中的第一位和第二位
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
查询
注意事项: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
相关文章推荐
- 如何用sqlite3来访问android真机中应用程序的数据库文件
- android:如何将数据库取出放进ListView,并进行增删查改的简单记录(14)
- android开发 如何通过web服务器访问MYSQL数据库并且使其数据同步到android SQLite数据库?
- 如何使用 sqlite3 访问 Android 手机的数据库
- Android编写简单的手机通讯录,只是存到数据库里面,并没有显示出来,下次更新显示到自定义适配器的通讯录(这个只是教大家SQLite数据库如何使用)
- 如何限定IP访问数据库
- 如何恢复一个非用户sa创建的数据库,且使用原用户创建者进行访问
- 如何学习数据库??《part1。几个简单的提问》
- [Question]如何将韩文数据存入到数据库中,并在数据库中正确显示
- 数据库访问简单实现---edainfo-model(三)——简单例子
- 一个简单的,适应多种数据库之间存取操作的数据库访问层
- 如何构建Informix分布式数据库访问
- 数据库访问简单实现edainfo-model(二)——简单例子
- 如何提高数据库访问效率
- 用CMP访问数据库,简单的,但不理解为什么URL不修改仍然可以运行
- servlet 定时操作,定时访问数据库,程序应该如何实现
- 谈谈如何通过WEB服务器访问内网数据库服务器的原理
- 正确使用DOM--如何访问网页元素
- 数据库访问简单实现edainfo-model(一)——简要介绍
- 访问数据库时如何解决并发问题