Android - 基于 SQL Cursor 创建一个非常大的 ListView
我有一个返回数千行的 SQLite 查询,我想使用 ListView
对其进行可视化。
为了保持 UI 线程响应,我在后台线程上创建了 ListAdapter
。
然而,花费最多时间(并且可能导致 ANR)的语句是 ListActivity.setListAdapter ,我必须在 UI 线程上执行它......有什么建议吗?
public class CursorTestActivity extends ListActivity { private static final String LOGTAG = "DBTEST"; private DatabaseManager mDbManager; private Cursor mCursor; private HandlerThread mIOWorkerThread; private Handler mIOHandler; private Handler mUIHandler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbManager = new DatabaseManager(this); mUIHandler = new Handler(); createIOWorkerThread(); log("creating cursor"); mCursor = mDbManager.getCursor(); // does db.query(...) startManagingCursor(mCursor); mIOHandler.post(new Runnable() { @Override public void run() { setMyListAdapter(); } }); log("onCreate done"); } private void setMyListAdapter() { log("constructing adapter"); // CustomCursorAdapter implements bindView and newView final CustomCursorAdapter listAdapter = new CustomCursorAdapter(this, mCursor, false); log("finished constructing adapter"); mUIHandler.post(new Runnable() { @Override public void run() { log("setting list adapter"); setListAdapter(listAdapter); // gets slower the more rows are returned log("setting content view"); setContentView(R.layout.main); log("done setting content view"); } }); } private void createIOWorkerThread() { mIOWorkerThread = new HandlerThread("io_thread"); mIOWorkerThread.start(); Looper looper = mIOWorkerThread.getLooper(); mIOHandler = new Handler(looper); } private void destroyIOWorkerThread() { if (mIOWorkerThread == null) return; Looper looper = mIOWorkerThread.getLooper(); if (looper != null) { looper.quit(); } } @Override public void onDestroy() { super.onDestroy(); if (mDbManager != null) mDbManager.close(); destroyIOWorkerThread(); } private static void log(String s) { Log.d(LOGTAG, s); } }
I have a SQLite query returning thousands of rows, which I want to visualize using a ListView
.
In order to keep my UI thread responsive, I create the ListAdapter
on a background thread.
However the statement that takes most time (and can cause ANR) is ListActivity.setListAdapter
which I have to execute on the UI thread... Any advice?
public class CursorTestActivity extends ListActivity { private static final String LOGTAG = "DBTEST"; private DatabaseManager mDbManager; private Cursor mCursor; private HandlerThread mIOWorkerThread; private Handler mIOHandler; private Handler mUIHandler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbManager = new DatabaseManager(this); mUIHandler = new Handler(); createIOWorkerThread(); log("creating cursor"); mCursor = mDbManager.getCursor(); // does db.query(...) startManagingCursor(mCursor); mIOHandler.post(new Runnable() { @Override public void run() { setMyListAdapter(); } }); log("onCreate done"); } private void setMyListAdapter() { log("constructing adapter"); // CustomCursorAdapter implements bindView and newView final CustomCursorAdapter listAdapter = new CustomCursorAdapter(this, mCursor, false); log("finished constructing adapter"); mUIHandler.post(new Runnable() { @Override public void run() { log("setting list adapter"); setListAdapter(listAdapter); // gets slower the more rows are returned log("setting content view"); setContentView(R.layout.main); log("done setting content view"); } }); } private void createIOWorkerThread() { mIOWorkerThread = new HandlerThread("io_thread"); mIOWorkerThread.start(); Looper looper = mIOWorkerThread.getLooper(); mIOHandler = new Handler(looper); } private void destroyIOWorkerThread() { if (mIOWorkerThread == null) return; Looper looper = mIOWorkerThread.getLooper(); if (looper != null) { looper.quit(); } } @Override public void onDestroy() { super.onDestroy(); if (mDbManager != null) mDbManager.close(); destroyIOWorkerThread(); } private static void log(String s) { Log.d(LOGTAG, s); } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
游标是延迟加载的,因此在第一次数据访问时会加载游标 - getCount 就是这样的访问。 setAdapter 方法正在对游标调用 getCount - 存在性能问题。
Cursors are lazy loaded therefore at first data access the cursor is loaded - getCount is such access. The setAdapter method is invoking getCount on cursor - there is the performance issue.