步骤:

1.新建一个继承SQLiteOpenHelper的帮助类

2.在MainActivity中定义LoaderManager和SimpleCursorAdapter

3.按顺序重写如下方法:initLoader来启动

onCreateLoader->onStartLoading(forceLoad启动时强制加载)->loadInBackground->onLoadFinished(adapter.swapCursor(data))->onLoaderReset(adapter.swapCursor(null))

*manager.restartLoader()数据改变时立刻加载

public class DBHelper extends SQLiteOpenHelper {
public static final String USERTABLE = "usertable";
private static final String DBNAME = "QF.DB";
private static final int CURRENTVERSION = 1; public DBHelper(Context context) {
super(context, DBNAME, null, CURRENTVERSION);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + USERTABLE + "(_id INTEGER PRIMARY KEY AUTOINCREMENT" +
",USERNAME,NICKNAME);");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}
/**
* Loader:自动监听数据源是否发生变化
*/
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> { private static SQLiteDatabase db;
private DBHelper dbHelper;
private SimpleCursorAdapter adapter;
private LoaderManager manager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DBHelper(this);
db = dbHelper.getReadableDatabase();
ListView listView = (ListView) findViewById(R.id.lv);
// 1.获得一个Loader管理器
manager = getSupportLoaderManager();
//2.初始化Loader
//1.Loader的唯一标识符
//2.初始化Loader时传递的参数
//3.Loader的回调
manager.initLoader(1, null, this);
//最后一个参数表示当数据源发生改变时,Cursor能够立马感知到数据源发生变化
adapter = new SimpleCursorAdapter(this,
R.layout.listview_item, null, new String[]{"USERNAME"}, new int[]{R.id.username},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(adapter);
} //当Loader创建时回调
//1.Loader的id
//2.初始化Loader的参数
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.d("lenve", "onCreateLoader: " + Thread.currentThread());
return new MyLoader(this);
} //当异步加载完成时调用该方法
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Log.d("lenve", "onLoadFinished: " + Thread.currentThread());
//交换Cursor
adapter.swapCursor(data);
} //当由于Loader重置导致Cursor失效时,调用该方法
@Override
public void onLoaderReset(Loader<Cursor> loader) {
Log.d("lenve", "onLoaderReset: " + Thread.currentThread());
adapter.swapCursor(null);
} public void addData(View view) {
ContentValues values = new ContentValues();
values.put("USERNAME", "李四i");
db.insert(DBHelper.USERTABLE, null, values);
//重启Loader
manager.restartLoader(1, null, this);
} static class MyLoader extends AsyncTaskLoader<Cursor> { public MyLoader(Context context) {
super(context);
} //在后台线程执行
@Override
public Cursor loadInBackground() {
Log.d("lenve", "loadInBackground: " + Thread.currentThread());
Cursor cursor = db.rawQuery("SELECT * FROM " + DBHelper.USERTABLE, null);
//在这里放回一个Cursor,该Cursor最终被onLoadFinished()方法接收到
return cursor;
} //开始加载时调用
@Override
protected void onStartLoading() {
super.onStartLoading();
Log.d("lenve", "onStartLoading: " + Thread.currentThread());
//第一次需要强制加载
forceLoad();
}
}
}

其中,适配器可以定义一个继承CursorAdapter的类,和baseAdapter的道理类似;且cursorAdapter的两个方法newView和bindView相当于BaseAdapter的getView方法的拆分

/**
* newView和bindView相当于BaseAdapter中的getView()方法
*/
public class MyAdapter extends CursorAdapter {
private LayoutInflater inflater; public MyAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
inflater = LayoutInflater.from(context);
} //初始化View
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = inflater.inflate(R.layout.listview_item, null);
ViewHolder holder = new ViewHolder();
holder.username = (TextView) view.findViewById(R.id.username);
view.setTag(holder);
return view;
} //给View上的控件绑定事件
//cursor.getColumnIndex("USERNAME")获取USERNAME字段的下标
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.username.setText(cursor.getString(cursor.getColumnIndex("USERNAME")));
} class ViewHolder {
TextView username;
}
}

Loader监听数据源的变化的更多相关文章

  1. 详解vuex结合localstorage动态监听storage的变化

    这篇文章主要介绍了详解vuex结合localstorage动态监听storage的变化,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 需求:不同组件间共用同一数据,当一个 ...

  2. HTML5 oninput实时监听输入框值变化的完美方案

    在网页开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理组合快 ...

  3. 【转载】实时监听输入框值变化的完美方案:oninput & onpropertychange

    oninput 是 HTML5 的标准事件,对于检测 textarea, input:text, input:password 和 input:search 这几个元素通过用户界面发生的内容变化非常有 ...

  4. 实时监听输入框值变化:oninput & onpropertychange

    结合 HTML5 标准事件 oninput 和 IE 专属事件 onpropertychange 事件来监听输入框值变化. oninput 是 HTML5 的标准事件,对于检测 textarea, i ...

  5. js/jquery 实时监听输入框值变化的完美方案:oninput & onpropertychange

    (1)     先说jquery, 使用 jQuery 库的话,只需要同时绑定 oninput 和 onpropertychange 两个事件就可以了,示例代码: $('#username').bin ...

  6. JS 获取和监听屏幕方向变化(portrait / landscape)

    移动设备的屏幕有两个方向: landscape(横屏)和portrait(竖屏),在某些情况下需要获取设备的屏幕方向和监听屏幕方向的变化,因此可以使用Javascript提供的 MediaQueryL ...

  7. 实时监听输入框值变化的完美方案:oninput & onpropertychange

    实时监听输入框值变化的完美方案:oninput & onpropertychange: 网址:http://www.cnblogs.com/lhb25/archive/2012/11/30/o ...

  8. 监听EditText的变化

    http://liangruijun.blog.51cto.com/3061169/729505 之前博客上的有关EditText的文章,只是介绍EditText的一些最基本的用法,这次来深入学习一下 ...

  9. input 即时搜索 监听输入值的变化

    在 Web 开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理 ...

随机推荐

  1. 第17月第28天 python yield

    1. class Fab(object): def __init__(self, max): self.max = max self.n, self.a, self.b = 0, 0, 1 def _ ...

  2. VMware12虚拟机中Ubuntu16.04安装CPU版本Caffe

    首先,可以自行下载VMware12进行安装,基本上都是直接点击‘下一步’直到安装完成,这里重点讲一下Ubuntu16及Caffe的安装步骤 第一步: 下载Ubuntu16.04版本的文件,这里给出链接 ...

  3. AutoMapper中用户自定义转换

    Custom Type Converters Sometimes, you need to take complete control over the conversion of one type ...

  4. 一文看懂汽车电子ECU bootloader工作原理及开发要点

    随着半导体技术的不断进步(按照摩尔定律),MCU内部集成的逻辑功能外设越来越多,存储器也越来越大.消费者对于汽车节能(经济和法规对排放的要求)型.舒适性.互联性.安全性(功能安全和信息安全)的要求越来 ...

  5. js里的回调函数

    function a(callback)  // 定义一个函数 ,需要传入的参数是callback  然后callback的类型为一个函数{console.log("callback还表示传 ...

  6. 【转】C++ map的基本操作和使用

    1.map简介 map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响较小,除了那个操作节点,对其它的节点都没有什么影响.对于迭代器来说,可以修改实值,而不能修改key. 2.map的功能 自 ...

  7. NTFS文件系统简介

    原文地址:http://www.cnblogs.com/watertao/archive/2011/11/28/2266595.html 1.简介 NTFS(New Technology File S ...

  8. 在Mac上安装GTK(go语言GUI)

    1.在终端输入:xcode-select --install 安装command line工具, 如果安装了Xcode, 就直接跳过该步骤 2. 在终端输入:ruby -e "$(curl ...

  9. sklearn聚类模型:基于密度的DBSCAN;基于混合高斯模型的GMM

    1 sklearn聚类方法详解 2 对比不同聚类算法在不同数据集上的表现 3 用scikit-learn学习K-Means聚类 4 用scikit-learn学习DBSCAN聚类 (基于密度的聚类) ...

  10. Java基础96 ajax技术的使用

    本文知识点(目录): 1.ajax的概念   2.使用ajax技术获取服务端的数据_实例   3.使用ajax技术检查用户名是否已存在_实例   4.使用ajax技术验证登录页面的用户名和密码_实例 ...