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

Android Fragment中SQLite查询与SimpleCursorAdapter使用问题

嘿,我来帮你搞定这两个问题,顺便给你揪出代码里几个容易踩坑的小细节:

解决你的Android SQLite与Fragment展示问题

问题1:Fragment中实例化BookDAO的Context错误

先看你Books Fragment的代码,有两个明显的问题:

  • 代码执行顺序错了:你在return v;之后才写实例化BookDAO的代码,这行代码永远不会被执行到!必须把业务逻辑代码放在return之前。
  • Context传递错误:BookDAO的构造函数需要的是Context对象,Fragment本身不是Context,不能直接传this。在Fragment里获取安全的Context可以用requireContext()(推荐,避免空指针),或者getActivity()(要确保Activity已绑定)。

修正后的Books Fragment onCreateView代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate布局
    View v = inflater.inflate(R.layout.fragment_books, container, false);
    
    // 正确实例化BookDAO并操作数据库
    BookDAO livreBdd = new BookDAO(requireContext());
    livreBdd.open(); // 别忘了打开数据库连接!
    List<Book> bookList = livreBdd.getAllBooks();
    livreBdd.close(); // 用完记得关闭连接,避免资源泄漏
    
    // 后续数据展示的代码放在这里
    
    return v;
}

问题2:用SimpleCursorAdapter展示数据

首先要明确:SimpleCursorAdapter是用来绑定Cursor类型数据到UI的,但你的getAllBooks()返回的是List<Book>,这里给你两种可行方案:

方案一:修改DAO返回Cursor(适配SimpleCursorAdapter)

把BookDAO的getAllBooks()改成返回Cursor(注意不要在DAO里关闭Cursor,交给Adapter管理):

public Cursor getAllBooksCursor() {
    // 注意:SimpleCursorAdapter要求Cursor必须包含名为_id的列,所以把id别名成_id
    String selectQuery = "SELECT id AS _id, isbn, title, resume FROM " + TABLE_NAME;
    return mdb.rawQuery(selectQuery, null);
}

然后需要调整你的布局:当前的fragment_books是三个TextView,只能展示单条数据,要展示所有条目得用ListView或RecyclerView。

先修改fragment_books.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.nabtech.android.nabilaffoauthor.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <ListView
        android:id="@+id/book_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

再创建列表项布局item_book.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="8dp">

    <TextView
        android:id="@+id/item_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/item_isbn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="@android:color/darker_gray"/>

    <TextView
        android:id="@+id/item_resume"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:layout_marginTop="4dp"/>
</LinearLayout>

最后在Fragment中初始化SimpleCursorAdapter:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_books, container, false);
    ListView listView = v.findViewById(R.id.book_list);

    BookDAO livreBdd = new BookDAO(requireContext());
    livreBdd.open();
    Cursor cursor = livreBdd.getAllBooksCursor();

    // 定义Cursor列名和布局View的对应关系
    String[] fromColumns = {BookDAO.TITLE, BookDAO.ISBN, BookDAO.RESUME};
    int[] toViews = {R.id.item_title, R.id.item_isbn, R.id.item_resume};

    // 初始化Adapter
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
            requireContext(),
            R.layout.item_book,
            cursor,
            fromColumns,
            toViews,
            0
    );

    listView.setAdapter(adapter);
    livreBdd.close();

    return v;
}

方案二:用ArrayAdapter展示List(更简单)

如果你不想改DAO的返回类型,直接用ArrayAdapter绑定List数据更省心。先创建自定义Adapter:

public class BookAdapter extends ArrayAdapter<Book> {

    public BookAdapter(Context context, List<Book> books) {
        super(context, 0, books);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        // 复用布局
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_book, parent, false);
        }

        Book book = getItem(position);
        if (book != null) {
            TextView titleTv = convertView.findViewById(R.id.item_title);
            TextView isbnTv = convertView.findViewById(R.id.item_isbn);
            TextView resumeTv = convertView.findViewById(R.id.item_resume);

            titleTv.setText(book.getTitle());
            isbnTv.setText(String.valueOf(book.getIsbn()));
            resumeTv.setText(book.getResume());
        }

        return convertView;
    }
}

然后在Fragment中使用:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_books, container, false);
    ListView listView = v.findViewById(R.id.book_list);

    BookDAO livreBdd = new BookDAO(requireContext());
    livreBdd.open();
    List<Book> bookList = livreBdd.getAllBooks();
    livreBdd.close();

    BookAdapter adapter = new BookAdapter(requireContext(), bookList);
    listView.setAdapter(adapter);

    return v;
}

额外的代码错误修正

我还发现你代码里几个小错误,不改会导致数据库操作失败:

  1. BookDAO中的TABLE_DROP拼写错误:" DROP TABLE IF RXISTS"应该是"DROP TABLE IF EXISTS "(注意空格和正确拼写)
  2. BookDAO中的TABLE_CREATE里,RESUME后面少了空格:"+ RESUME + "TEXT );"应该是"+ RESUME + " TEXT );"
  3. DatabaseHandler中的BOOK_TABLE_DROP少了空格:"DROP TABLE IF EXISTS" + BOOK_TABLE_NAME + ";"应该是"DROP TABLE IF EXISTS " + BOOK_TABLE_NAME + ";"

这些小错误会导致SQL语句语法错误,创建/删除表失败,记得修正!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:23:46