如何使用SimpleCursorLoader在ListView中显示元素
使用SimpleCursorLoader在Fragment的ListView中显示SQLite数据的实现指南
嘿,我来帮你搞定用SimpleCursorLoader在Fragment的ListView里展示SQLite数据的事儿。这玩意儿能帮你异步加载数据,避免主线程阻塞,让界面体验更流畅。咱们一步步来:
第一步:让Fragment实现LoaderCallbacks接口
你的Tab3Fragment需要实现LoaderManager.LoaderCallbacks<Cursor>接口,这样才能和Loader框架正常交互。修改类定义:
public class Tab3Fragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { // 后续变量定义放在这里 }
第二步:调整DBHandler的初始化时机
注意哦,getContext()在Fragment的onCreateView之前可能是null的,别在成员变量里直接初始化dbHandler,把它移到onCreateView或者onViewCreated里更稳妥:
private DBHandler dbHandler; private ListView listView; private SimpleCursorAdapter adapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.tab3_frag, container, false); // 初始化DBHandler dbHandler = new DBHandler(getContext(), null, null, 4); // 找到布局里的ListView(替换成你实际的ID) listView = view.findViewById(R.id.list_view_students); return view; }
第三步:初始化CursorAdapter并启动Loader
在onViewCreated方法里配置列表适配器,然后启动Loader:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 定义要从Cursor取的列,以及对应列表项布局里的控件ID String[] fromColumns = { Contract.Student_Table.STUDENTS_COLUMN_NAME, Contract.Student_Table.STUDENTS_COLUMN_AGE }; int[] toViews = { R.id.tv_student_name, // 替换成你列表项里的TextView ID R.id.tv_student_age }; // 初始化SimpleCursorAdapter,初始Cursor传null,Loader会帮我们加载数据 adapter = new SimpleCursorAdapter( getContext(), R.layout.item_student, // 替换成你的列表项布局文件 null, fromColumns, toViews, 0 ); listView.setAdapter(adapter); // 启动Loader,第一个参数是唯一的Loader ID,随便设个数字就行 getLoaderManager().initLoader(1, null, this); }
第四步:实现LoaderCallbacks的三个核心方法
这部分是Loader的核心逻辑,负责创建Loader、处理加载完成的数据、重置Loader:
onCreateLoader:创建SimpleCursorLoader并定义查询逻辑
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { // 必须包含_ID列!CursorAdapter要求Cursor必须有这个列,不然会报错 String[] projection = { Contract.Student_Table._ID, Contract.Student_Table.STUDENTS_COLUMN_NAME, Contract.Student_Table.STUDENTS_COLUMN_AGE }; // 可以按需添加查询条件、排序规则 String sortOrder = Contract.Student_Table.STUDENTS_COLUMN_NAME + " ASC"; return new SimpleCursorLoader(getContext()) { @Override public Cursor loadInBackground() { // 在后台线程执行SQL查询,避免阻塞主线程 return dbHandler.getReadableDatabase().query( Contract.Student_Table.TABLE_NAME, projection, null, // 查询条件,按需设置 null, // 条件参数 null, null, sortOrder ); } }; }
onLoadFinished:加载完成后更新列表数据
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // 把加载好的Cursor交给适配器,列表会自动刷新 adapter.swapCursor(data); }
onLoaderReset:重置Loader时清理Cursor
@Override public void onLoaderReset(Loader<Cursor> loader) { // 清空适配器的Cursor,避免内存泄漏 adapter.swapCursor(null); }
额外提示:数据更新后刷新列表
当你对SQLite数据库做了增删改操作后,只需要调用下面的代码就能让Loader重新加载数据,自动更新列表:
getLoaderManager().restartLoader(1, null, this);
内容的提问来源于stack exchange,提问作者Jon Goe
相关产品推荐
相关产品推荐

