使用Loader实时查询本地数据库用法

在看Android的文档时,看到了这么一个东西: Loader

究竟是什么东西呢?

Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics:

1、They are available to every Activity and Fragment.  //支持Activity和Fragment

2、They provide asynchronous loading of data.    //可以进行异步下载

3、They monitor the source of their data and deliver new results when the content changes. //当数据源改变时能及时通知客户端

4、They automatically reconnect to the last loader‘s cursor when being recreated after a configuration change. Thus, they don‘t need to re-query their data. //发生configuration change时自动重连接

Loader技术为我们提供的核心类有:

    • LoaderManager:可以通过Activity或者的Fragment的getLoaderManager()方法得到LoaderManager,用来对Loader进行管理,一个Activity或者Fragment只能有一个LoaderManager。
    • LoaderManager.LoaderCallbacks:用于同LoaderManager进行交互,可以在其中创建Loader对象。
    • AsyncTaskLoader:抽象类,可以进行异步加载数据的Loader,貌似内部也是通过AsynTask实现的,可以通过继承它构建自己的Loader,也可以使用现有的子类,例如异步查询数据库可以使用CursorLoader。

      使用Loader一般可以经过以下步骤:

      1、初始化Loader,可以使用initLoader(intid, Bundle args, LoaderManager.LoaderCallbackscallback);方法进行初始化。

      id:标识Loader的ID,一个Activity或者Fragment只能有一个LoaderManager,但可以有多个Loader,通过ID区 分。在新建Loader时,如果发现已经有相同ID的Loader就会复用该Loader,而不会重新创建。
      args:传给新建Loader的参数。

      Callback:回调接口。

      2、实现LoaderManager.LoaderCallbacks中的方法,LoaderManager.LoaderCallbacks中需要实现的方法有:
      publicLoader onCreateLoader(int id, Bundle args):创建新的Loader,id为LoaderID,如果已经有相同ID的Loader就会复用该Loader,而不会重新创建。 args为初始化时传递的参数。该方法开始异步查询,并返回一个泛型类,如果是查询数据库可以返回一个CursorLoader,可以返回自定义的Loader。public voidonLoadFinished(Loader loader, D data):异步查询结束的会调用这个方法,并返回查询结果 data。public void onLoaderReset(Loader loader): 当调用Loader.reset()将Loader数据清空时,但在系统销毁Loader时会自动调用Loader.reset()方法,我们一般不需要手动调用,只需要在onLoaderReset方法中,将使用Loader的移除。

      3、使用 restartLoader(intid, Bundle args, LoaderManager.LoaderCallbacks callback)方法进行数据更新,和初始化一个,如果有相同id的Loader存在,会复用Loader,并清空原有Loader中的数据,如果没有就新建一个。这个方法一般使用在需要更新数据时,例如下面例子中,在搜索关键改变时,需要调用这个方法,从新异步查询数据。

public class CollectDetail extends Activity implements LoaderCallbacks<Cursor> {

private ListView listview;
private SimpleCursorAdapter adapter;
private LoaderManager loaderManager;
private MySQLiteOpenHelper openHelper;
private static SQLiteDatabase db;
private TextView textview_empty;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//去掉标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_collect_detail);

openHelper = new MySQLiteOpenHelper(this);

//获取DB对象
db = openHelper.getWritableDatabase();

listview = (ListView) findViewById(R.id.collect_listView);
textview_empty = (TextView) findViewById(R.id.textview_collect_empty);//当listview空时显示

//创建适配器(此时数据为空"null")
adapter = new SimpleCursorAdapter(this, R.layout.collect_listview_item, null, new String []{"title","nickname","create_time"}, new int[]{R.id.collect_item_title,R.id.collect_item_nickname,R.id.collect_item_create_time},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

listview.setAdapter(adapter);

listview.setEmptyView(textview_empty);//设置无数据时显示的view

//获取loadermanager管理者对象
loaderManager = getLoaderManager();
//初始化loader

//第一个参数用于标记一个loader.因为loaderManager可以管理多个loader

第二个参数"Bundle args"  为查询条件,无条件是为null即可

第三个参数为初始化loader之后的回调方法(LoaderCallbacks<Cursor>) 一般让此时的Activity去实现

loaderManager.initLoader(1, null,this );

//给显示数据的listview设置条目点击监听
listview.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//跳转到详情界面
String sql ="select _id,title,nickname,create_time,flag from collect";

Cursor cursor = db.rawQuery(sql, null);
cursor.moveToPosition(position);//将cursor游标移动至此position的位置

//从cursor中获取此条目的详细信息
String _id = cursor.getString(cursor.getColumnIndex("_id"));
String title = cursor.getString(cursor.getColumnIndex("title"));
String nickname = cursor.getString(cursor.getColumnIndex("nickname"));
String create_time = cursor.getString(cursor.getColumnIndex("create_time"));
int flag = cursor.getInt(cursor.getColumnIndex("flag"));

Intent intent = new Intent();
Bundle bundle =new Bundle();
bundle.putString("id", _id);
bundle.putString("title", title);
bundle.putString("nickname", nickname);
bundle.putString("create_time", create_time);
bundle.putInt("flag",flag);
intent.putExtras(bundle);

intent.setClass(CollectDetail.this, ItemListview.class);

startActivity(intent);

}
});

//注册上下文菜,用于 删除此条目,并实施更新listview上的数据
registerForContextMenu(listview);

}
//创建出上下文菜单

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
getMenuInflater().inflate(R.menu.collect_listview, menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
//当上下文菜单中的条目被点击时,删除此条目,并重启loader
@Override
public boolean onContextItemSelected(MenuItem item) {

AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
int position = menuInfo.position;

Cursor cursor = adapter.getCursor();//从适配器中获取到cursor

cursor.moveToPosition(position);
String _id = cursor.getString(cursor.getColumnIndex("_id"));//获取到此位置信息的_id更具此_id进行删除操作

String sql ="delete from collect where _id=‘"+_id+"‘";
db.execSQL(sql);

loaderManager.restartLoader(1, null, this);//通过loaderManager重启loader
return super.onContextItemSelected(item);
}

//执行接口回调时,必须要执行的3个方法

//首先获取到loader对象

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
   MyAsyncTaskLoader loader = new MyAsyncTaskLoader(this);
    return loader;  
}

//当数据加载完成时调用的方法,此时使适配器置换数据为"data"

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

adapter.swapCursor(data);

}

//当loader重启是调用的方法,此时将适配器中的数据置换为空

@Override
public void onLoaderReset(Loader<Cursor> loader) {

adapter.swapCursor(null);

}

//写一个类继承AsyncTaskLoader<Cursor>(此类必须定义为静态static类型的)
public static class MyAsyncTaskLoader extends AsyncTaskLoader<Cursor>{

public MyAsyncTaskLoader(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onStartLoading() {
// TODO Auto-generated method stub
super.onStartLoading();
  forceLoad();//必须要写此方法,使其能够向下执行loadInBackground
}

@Override
public Cursor loadInBackground() {
String sql = "select _id,title,nickname,create_time from collect";
Cursor cursor_collect = db.rawQuery(sql, null);

return cursor_collect;
}

}

}

时间: 2024-08-11 19:25:17

使用Loader实时查询本地数据库用法的相关文章

Windows Phone本地数据库(SQLCE):11、使用LINQ查询数据库(翻译) (转)

这是“windows phone mango本地数据库(sqlce)”系列短片文章的第十一篇. 为了让你开始在Windows Phone Mango中使用数据库,这一系列短片文章将覆盖所有你需要知道的知识点.我将谈谈在windows phone mango本地数据库里怎么使用LINQ查询数据库. 1.数据库查询是什么 在windows phone上,语言集成查询(LINQ)被用作查询数据库.LINQ常用于表示对象和实际数据之间的连接.LINQ to SQL中的查询使用和LINQ 的查询相同的语法

mysql数据库(三):查询的其他用法

一. 查询—IN的用法 语法:select ... from 表名 where 字段 a in (值b, 值c, 值d...) 等价于 select ... from 表名 where 字段a=值b or 字段a=值c or 字段a=值d; 例如,查询学生表里学生编号为1401001或者1401002或者1401003的学生信息 select * from student where id=1401001 or id=1401002 or id=1401003; select * from st

HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)

1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息. 但是cookie有下面几个问题: a:大小:cookies的大小被限制在4KB b:带宽:cookies随HTTP事务一起被发送,因此会浪费一部分发送的cookies时使用的带宽. c:复杂性:要正确的操纵cookies是很困难的. Web Storage分为两种: <1>sessionStorage 将数

Html5 学习系列(六)Html5本地存储和本地数据库

一个网站如何能在客户的浏览器存储更多的数据呢? 在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cookie的限制也就逼迫网站存储数据尽量精简,想存储复杂的.关系型的用户数据就根本不可能了.但是进入Html5时代,这一切都不叫事... 一.本地存储由来的背景 众所周知Html4时代Cookie的大小.格式.存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie.但是C

Html5本地存储和本地数据库

一个网站如何能在客户的浏览器存储更多的数据呢? 在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cookie的限制也就逼迫网站存储数据尽量精简,想存储复杂的.关系型的用户数据就根本不可能了.但是进入Html5时代,这一切都不叫事... 一.本地存储由来的背景 众所周知Html4时代Cookie的大小.格式.存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie.但是C

HTML5本地数据库(WebSQL)[转]

除了sessionStorage和localStorage外,HTML5还支持通过本地数据库进行本地数据存储,HTML5采用的是"SQLite"这种文件型数据库,该数据库多集中在嵌入式设备上,熟悉IOS/Android开发的同学,应该对SQLite数据库比较熟悉. webSql允许我们直接通JS的API在浏览器端创建一个本地的数据库,而且支持标准的SQL的CRUD操作,让离线的Web应用更加方便的存储结构化的数据.接下里介绍一下本地数据的相关API和用法. 操作本地数据库的最基本的步骤

sql server 警报管理,实时监听数据库动向,运筹帷幄之中

原文:sql server 警报管理,实时监听数据库动向,运筹帷幄之中 工作这么多年了,无论是身边的同学还是同事,发现只要搞程序员的都有一个通病---懒.懒到谁都不愿意加班,尤其是"义务"加班.即使大家都不愿意加班,但是很多时候项目赶着上线或者上线之后出错啊什么的,总得有人看着,这时候就诞生了一种新的工作制度,叫做7*24.顾名思义就是这种岗位实时都得有人看着,这确实是一件让人头疼的事情.虽然说在项目刚上线不可避免的得有7*24,但是我们可以尽量减少7*24的工作量(ps:因为7*24

SQL Server2016 新功能实时查询统计信息

SQL Server2016 新功能实时查询统计信息 很多时候有这样的场景,开发抱怨DBA没有调优好数据库,DBA抱怨开发写的程序代码差,因此,DBA和开发都成为了死对头,无法真正排查问题. DBA只能使用Windows性能监视器,SQL Server内置的活动监视器.SQL Trace.SQL Profiler.Performance Dashboard等工具,或者使用执行计划来查看查询成本. 为了让DBA有更多有效工具排查问题,SQL Server2016推出了很多新功能,其中一项功能是 L

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况