Android 使用Loader示例
Android 3.0 sdk,引入了很多新api,比如Loader。和Fragment类似(编写兼容android1.6的fragment),该api也可在Android 1.6以上版本执行。
以下介绍如何编写Loader,实现对ListView的异步加载。效果如图:
示例中有一个后台线程每隔3秒更新数据库的长江记录,将记录改为“长江”或“Long River”。ListView无需监控数据库变化,基于Loader,会自动更新。实际上这里面是观察者模式,无非是系统自带了,只需调用即可,无需自己构造观察者。
这个示例也是完整的sqlite+content provider+cursor adapter+listview+loader组合示例。
编写前的准备类似编写兼容android1.6的fragment,需要导入jar包。
另外,2.3以前的Activity类没有提供一些Loader的帮助方法,需要让自己的Activity实现类继承FragmentActivity:
public class ListViewActivity extends FragmentActivity
本示例是在在视图显示中使用Theme基础上实现的。
Activity类和RiverContentProvider类做了修改。
Activity类:
public class ListViewActivity extends FragmentActivity { private ListView riverListView; private SimpleCursorAdapter adapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initLoader(); setRiverListViewAdapter(); } private void initLoader() { getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { Log.d("list", "on create loader"); CursorLoader cursorLoader=new CursorLoader(ListViewActivity.this, RiverContentProvider.CONTENT_URI, new String[] { RiverContentProvider._ID, RiverContentProvider.NAME, RiverContentProvider.INTRODUCTION }, null, null, null); //cursorLoader.setUpdateThrottle(1000); return cursorLoader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { Log.d("list", "on loader finished"); adapter.swapCursor(cursor); } @Override public void onLoaderReset(Loader<Cursor> loader) { Log.d("list", "on loader reset"); adapter.swapCursor(null); } }); } private void setRiverListViewAdapter() { riverListView = (ListView) this.findViewById(R.id.riverList); Cursor cursor = managedQuery(RiverContentProvider.CONTENT_URI, null, null, null, null); adapter = new SimpleCursorAdapter(this, R.layout.row, cursor, new String[] { RiverContentProvider.NAME, RiverContentProvider.INTRODUCTION }, new int[] { R.id.riverName, R.id.riverIntroduction }, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); riverListView.setAdapter(adapter); }
主要是增加了initLoader方法。这里主要是实现了LoaderCallbacks接口。其中:
onCreateLoader,在创建activity时跟着onCreate会调用一次
onLoadFinished,每次改变和Loader相关的数据库记录后会调用一次
onLoaderReset,在关闭Activity时调用,释放资源
然后,在Content provider中,要调用类似观察者模式中通知的方法,即,在update方法中通知观察者记录改变,在query方法中注册观察者,这样通知来了可接收并处理。
update方法:
@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int returnValue = database.update("rivers", values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return returnValue; }
query方法:
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){ Cursor cursor = database.query("rivers", projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架