You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Java SQLite条件查询后ListView加载崩溃问题求助

Android SQLite条件查询崩溃:Spinner选分组后加载ListView无响应最终崩溃

问题场景

已实现SQLite分组数据正常加载至Spinner,但选择分组后进度圈持续运行,最终APP崩溃,无明显报错信息。


排查与修复方案

1. 解决主线程阻塞问题

数据库查询属于耗时操作,若直接在主线程执行会引发ANR(应用无响应)进而崩溃。必须将查询逻辑放到子线程执行:

// 在SelectContactsActivity的Spinner选择事件中
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        String selectedGroup = parent.getItemAtPosition(position).toString();
        progressDialog.show();
        
        // 用AsyncTask执行异步查询
        new AsyncTask<String, Void, Cursor>() {
            @Override
            protected Cursor doInBackground(String... params) {
                // 子线程中执行数据库查询
                return contactsDbAdapter.getContactsByGroup(params[0]);
            }

            @Override
            protected void onPostExecute(Cursor cursor) {
                // 主线程更新ListView并关闭进度圈
                customContactsAdapter.changeCursor(cursor);
                progressDialog.dismiss();
            }
        }.execute(selectedGroup);
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {}
});

2. 修复Cursor内存泄漏

未正确关闭旧Cursor会导致内存耗尽,需在自定义Adapter中处理:

public class CustomContactsAdapter extends CursorAdapter {
    // ... 其他实现代码
    @Override
    public void changeCursor(Cursor newCursor) {
        Cursor oldCursor = getCursor();
        super.changeCursor(newCursor);
        // 关闭旧Cursor释放资源
        if (oldCursor != null && !oldCursor.isClosed()) {
            oldCursor.close();
        }
    }

    // Activity销毁时关闭数据库连接
    @Override
    protected void onDestroy() {
        super.onDestroy();
        contactsDbAdapter.close();
        if (customContactsAdapter.getCursor() != null) {
            customContactsAdapter.getCursor().close();
        }
    }
}

3. 优化SQL查询性能

若分组下数据量过大或查询无索引,会导致查询超时崩溃:

  • 给分组字段添加索引:
    // 在ContactsDetailsDbAdapter的表创建语句中添加索引
    private static final String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
            + KEY_ID + " INTEGER PRIMARY KEY,"
            + KEY_GROUP + " TEXT,"
            + // 其他字段
            + "CREATE INDEX idx_contact_group ON " + TABLE_CONTACTS + "(" + KEY_GROUP + ");";
    
  • 避免SELECT *,只查询ListView需要的字段,减少数据传输量。

4. 强制捕获异常获取报错信息

即使表面无报错,也能通过try-catch捕获异常日志:

// 在AsyncTask的doInBackground中添加异常捕获
@Override
protected Cursor doInBackground(String... params) {
    try {
        return contactsDbAdapter.getContactsByGroup(params[0]);
    } catch (Exception e) {
        e.printStackTrace(); // 查看Logcat的Error级别日志,定位具体崩溃原因
        return null;
    }
}

内容的提问来源于stack exchange,提问作者Maria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:15:01