Loader监听数据源的变化
步骤:
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; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现