Android开发 - (适配器)Adapter类中CursorAdapter实现类详细解析

简介

  • 用于将数据库查询结果(Cursor)绑定到 ListView 或 GridView

具体作用

  • Cursor对象中的数据与AdapterView组件(如ListView、GridView等)进行绑定。以下是CursorAdapter的主要作用

    数据源绑定

    • 数据源连接CursorAdapter通过Cursor对象作为数据源,实现了从数据库其他数据源(如ContentResolver查询结果)中读取数据的功能。这使得开发者能够轻松地将存储在数据库中的数据展示在UI组件
    • 自动更新:当Cursor对象中的数据发生变化时,CursorAdapter能够自动感知并更新AdapterView中显示的数据,无需手动刷新

    自定义显示逻辑

    • 方法重写:通过继承CursorAdapter重写其方法(如newView()bindView()getItemId()等),开发者可以实现自定义的显示逻辑,如数据的过滤排序格式化显示
    • UI定制:结合自定义的布局文件,开发者可以定制每个列表项或网格项的UI,以满足不同的设计需求

    性能优化

    • 视图重用CursorAdapter内部实现了视图的重用机制,即在滚动列表或网格时,会尽可能重用已存在的视图对象,以减少创建和销毁视图的开销,从而提高性能
    • 数据驱动:由于CursorAdapter直接绑定到数据源上,因此它能够根据数据源的变化动态地更新UI,这种数据驱动的方式有助于减少不必要的UI更新操作

    简化开发

    • 减少代码量:通过使用CursorAdapter,开发者可以减少编写适配器代码的工作量,因为CursorAdapter已经提供了一套处理Cursor对象AdapterView组件之间交互的框架
    • 提高开发效率:由于CursorAdapter的灵活性和易用性,开发者可以更快地实现数据展示功能,从而提高开发效率

参数、方法解析

  • CursorAdapter(Context context, Cursor cursor, int flags, int layout)CursorAdapter是一个抽象类,因此它无法被直接使用new关键词实例化,需要通过继承重写

    // 自定义 CursorAdapter 类  
    public class MyCustomCursorAdapter extends CursorAdapter {  
      
        private LayoutInflater mInflater;  
      
        public MyCustomCursorAdapter(Context context, Cursor cursor) {  
            super(context, cursor, 0); // 调用父类的构造方法  
            mInflater = LayoutInflater.from(context);  
        }  
      
        @Override  
        public View newView(Context context, Cursor cursor, ViewGroup parent) {  
            // 根据布局资源创建新的视图实例  
            return mInflater.inflate(R.layout.my_list_item, parent, false);  
        }  
      
        @Override  
        public void bindView(View view, Context context, Cursor cursor) {  
            // 将 Cursor 中的数据绑定到视图上  
            TextView textView = view.findViewById(R.id.my_text_view);  
            textView.setText(cursor.getString(cursor.getColumnIndexOrThrow("my_column_name")));  
            // 其他绑定操作...  
        }  
    }  
    
    // 在你的 Activity 或 Fragment 中实例化它  
    private MyCustomCursorAdapter adapter;
    // 假设你已经有了Cursor对象cursor  
    Cursor cursor = getContentResolver().query(MyContentProvider.CONTENT_URI, null, null, null, null);  
    // 实例化自定义的CursorAdapter  
    adapter = new MyCustomCursorAdapter(context, cursor); 
    
    • 参数解析
      • context:应用程序的上下文,用于访问资源布局文件等;在创建视图加载资源等操作时需要使用
      • cursor:一个指向数据库查询结果的Cursor对象,包含了要展示在列表中的数据;适配器通过Cursor遍历数据,并将其绑定到视图上
      • flags(可选):用于确定适配器行为的标志,可以是FLAG_AUTO_REQUERYFLAG_REGISTER_CONTENT_OBSERVER的组合;FLAG_AUTO_REQUERY已被弃用,但FLAG_REGISTER_CONTENT_OBSERVER可以用于注册一个内容观察者,以便在数据变化时收到通知。然而,现代应用中更推荐使用LoaderManagerCursorLoader来处理数据更新
      • int layout(可选):布局文件的资源ID,用于定义列表项的外观;如果指定了此参数,则适配器将使用此布局来创建新的视图。否则,需要在子类中覆盖newView()方法来自定义视图的创建
  • Cursor cursor = getContentResolver().query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);

    Cursor cursor = getContentResolver().query(MyContentProvider.CONTENT_URI, null, null, null, null);
    
    • 参数解析
      • uri:这是你要查询的内容提供者的URI。这个URI应该在你的内容提供者类中定义,并指向你想要查询的数据集
      • projection:这是一个字符串数组,指定了你想要从查询结果中选择的列。如果你传递null,那么将选择所有列
      • selection:这是一个用于限制哪些行应该被包含在结果集中的选择条件字符串。如果你传递null,那么将选择所有行
      • selectionArgs:这是一个与选择条件中使用的占位符相对应的值的数组。如果你的选择条件字符串中没有占位符(即?字符),或者你没有使用选择条件,那么这个参数应该是null
      • sortOrder:这是一个指定结果集排序方式的字符串。如果你传递null,那么结果集的顺序将是不确定的
  • adapter.getCount()返回Cursor中的行数,即AdapterView中项的总数(int)

  • adapter.getItem(int position):根据位置获取Cursor中对应的数据项。然而,在CursorAdapter的实现中,这个方法通常只是简单地返回Cursor对象本身并将其位置移动到指定的位置。实际上,并不建议直接使用返回的Cursor对象,因为这会破坏Cursor的位置状态

    // 假设你有一个ArrayAdapter<String>,它管理着一个字符串数组  
    String[] mList = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"};
    // 假设你已经继承重写了CursorAdapter抽象类,让我们实例化它
    MyCustomCursorAdapter adapter = new MyCustomCursorAdapter(context, cursor); 
    int position = 0; // 假设你想获取第一个项 
    String item = adapter.getItem(position);	//这里假设yourStringList是String类型的列表,此时,item就是位于position位置的字符串项
    
    • 参数解析
      • position:获取指定位置的数据项
  • adapter.getView(int position, View convertView, ViewGroup parent)获取数据项的视图,用于在ListViewSpinner中显示数据。这个方法通常不需要直接调用而是由系统在需要显示列表项时自动调用

    // 假设你已经继承重写了CursorAdapter抽象类,让我们实例化它
    MyCustomCursorAdapter adapter = new MyCustomCursorAdapter(context, cursor); 
    ListView listView = view.findViewById(android.R.id.listView_1);
    View view = adapter.getView(position, null, listView);
    
    • 参数解析
      • position:要获取视图的数据项的位置(索引)
      • convertView:可复用的视图对象,用于优化列表性能,如果为null,表示要获取一个新的视图对象;如果不为null,则可以重复使用该视图对象,避免重复创建
      • parent:父视图,即该视图将被添加到的父容器(例如ListView)
  • newView(Context context, Cursor cursor, ViewGroup parent);:用于创建一个新的视图来展示Cursor当前指向的数据。这个方法只会在需要时才被调用,比如在实例化CursorAdapter时,或者在数据增加导致需要更多视图时

    @Override  
    public void bindView(View view, Context context, Cursor cursor) {  
        // 假设R.layout.list_item中有一个TextView,其ID为android.R.id.text1  
        TextView textView = view.findViewById(android.R.id.text1);  
      
        // 从游标中获取数据并设置到TextView上  
        // 注意:这里假设游标中有一列名为"column_name"的数据  
        String data = cursor.getString(cursor.getColumnIndexOrThrow("column_name"));  
        textView.setText(data);  
      
        // 如果你的布局中有其他视图需要绑定数据,也可以在这里做  
    }
    
    • 参数解析
      • context:应用程序的全局信息接口,用于访问应用的资源类加载器等。在创建视图时,可能需要使用上下文来获取布局文件、主题信息
      • cursor游标对象,它包含了要从数据库中检索的数据。在newView方法中,Cursor已经被移动到了正确的位置(即与当前要创建的视图相关联的数据行)
      • parent:新创建的视图将要附加到的父视图组。这个参数在创建视图时可能用于确定布局参数或进行其他与父视图相关的初始化
  • bindView(View view, Context context, Cursor cursor):将Cursor当前指向的数据绑定到传入的视图上。这个方法在绘制Item之前一定会被调用,包括在重绘时。通过这个方法,可以将Cursor中的数据填充到视图的各个组件中(如TextView、ImageView等)

    @Override  
    public void bindView(View view, Context context, Cursor cursor) {  
        // 假设你有一个自定义的列表项布局,里面有一个TextView用于显示数据  
        // 并且这个TextView在你的布局文件中有一个特定的ID,比如R.id.my_text_view  
      
        // 通过findViewById获取TextView的引用  
        TextView textView = view.findViewById(R.id.my_text_view);  
      
        // 从游标中获取数据。这里假设游标中有一列名为"name"的数据  
        // 使用getColumnIndexOrThrow来确保列存在,并获取其索引  
        int columnIndex = cursor.getColumnIndexOrThrow("name");  
      
        // 使用索引从游标中获取数据,并设置到TextView上  
        String name = cursor.getString(columnIndex);  
        textView.setText(name);  
      
        // 如果你的列表项布局中还有其他组件需要绑定数据,  
        // 你可以按照相同的方式获取这些组件的引用,并从游标中检索相应的数据来设置它们  
      
        // 例如,如果你的布局中还有一个ImageView用于显示头像,  
        // 你可以这样获取它并设置图片(这里只是示例,实际上设置图片会更复杂)  
        // ImageView imageView = view.findViewById(R.id.my_image_view);  
        // // 假设你有一个方法可以从游标的某个列中加载图片  
        // // imageView.setImageBitmap(loadImageFromCursor(cursor));  
    }  
      
    // 注意:上面的loadImageFromCursor是一个假设的方法,  
    // 你需要根据实际情况来实现从游标加载图片的逻辑。
    
    • 参数解析
      • view:已经存在的视图,这个视图可能是之前通过newView方法创建的,也可能是通过视图重用机制(convertView不为null时)传递进来的
      • context:应用程序的全局信息接口,用于访问应用的资源类加载器等。在创建视图时,可能需要使用上下文来获取布局文件、主题信息
      • cursor游标对象,同样包含了要从数据库中检索的数据。在bindView方法中,Cursor也已经被移动到了正确的位置
  • adapter.changeCursor(Cursor cursor):用于更改适配器底层的游标为新传入的游标。如果适配器当前已经有一个游标对象,那么这个方法会先关闭旧的游标,然后再将新的游标设置给适配器。这个方法通常用于在数据发生变化时刷新列表

    // 假设MyCursorAdapter这是你的CursorAdapter子类
    MyCursorAdapter adapter = new MyCursorAdapter(context, null, 0);  
      
    // 假设你有一个ListView,并且已经将myCursorAdapter设置为了它的适配器  
    ListView listView = findViewById(R.id.my_list_view);  
    listView.setAdapter(adapter);  
      
    // ... 在某个地方,你获取了一个新的Cursor ...  
    // 例如,从数据库查询中  
    Cursor newCursor = databaseHelper.querySomeData();  
      
    // 现在,你想用新的Cursor来更新ListView显示的数据  
    // 你可以通过调用myCursorAdapter的changeCursor方法来实现  
      
    // 首先,检查当前是否有Cursor被设置,并且它没有被关闭  
    if (adapter.getCursor() != null && !adapter.getCursor().isClosed()) {  
        // 关闭旧的Cursor(这是可选的,但通常是一个好习惯,以避免内存泄漏)  
        adapter.getCursor().close();  
    }  
      
    // 然后,将新的Cursor设置给适配器  
    adapter.changeCursor(newCursor);  
    
    • 参数解析
      • cursor新的游标对象,用于替换当前适配器中正在使用的游标
  • adapter.getItemId(int position):返回适配器中指定位置的数据行的ID。在CursorAdapter中,这个方法通常通过CursorgetLong(mRowIDColumn)方法来实现,其中mRowIDColumnCursor中用于存储行ID的列的索引。这个方法在需要唯一标识列表中每一项时非常有用,比如在使用ListView的复选框模式时

    long itemId = -1; // 初始化一个变量来存储ID,这里先给它一个默认值(比如-1,表示无效ID)  
    if (adapter != null && adapter.getCursor() != null && !adapter.getCursor().isClosed()) {  
        // 确保游标有效  
        int positionYouWant = 0; // 这里替换为你想要获取ID的列表项的位置  
        if (positionYouWant >= 0 && positionYouWant < adapter.getCount()) {  
            // 确保位置在有效范围内  
            itemId = adapter.getItemId(positionYouWant); // 现在你可以获取ID了  
        }  
    }  
    // 现在你可以使用itemId变量了
    
    • 参数解析
      • int position:要获取行ID的数据的索引位置
  • cursor.close();:关闭游标,释放资源

    if (cursor != null && !cursor.isClosed()) {  
        cursor.close();  
    } 
    

使用场景解析

  • CursorAdapterAndroid 中用于将 Cursor 对象的数据绑定到 ListViewGridView其他可滚动视图中的适配器。Cursor 通常是从 SQLite 数据库内容提供者(Content Provider)中获取的数据结果集。CursorAdapter 适用于处理从数据库或内容提供者中读取的数据,并将这些数据动态地显示在 UI 组件中。以下是 CursorAdapter 的主要使用场景:

    显示数据库中的数据

    • 场景描述:从 SQLite 数据库中查询数据并在 ListViewGridView 中展示,例如显示联系人列表消息记录任务清单

    • 示例:假设你有一个 SQLite 数据库表来存储联系人信息,你可以使用 CursorAdapter 来显示这些联系人

      • 数据库表结构

        CREATE TABLE contacts (
            _id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            phone_number TEXT
        );
        
      • 自定义CursorAdapter类ContactsCursorAdapter.java

        package com.example.cursoradapterexample;
        
        import android.content.Context;
        import android.database.Cursor;
        import android.provider.ContactsContract;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.CursorAdapter;
        import android.widget.TextView;
        
        /**
         * 自定义 CursorAdapter,用于将联系人数据从游标绑定到 ListView。
         */
        public class ContactsCursorAdapter extends CursorAdapter {
        
            public ContactsCursorAdapter(Context context, Cursor cursor, int flags) {
                super(context, cursor, flags);
            }
        
            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                // 使用自定义布局文件创建新视图
                LayoutInflater inflater = LayoutInflater.from(context);
                return inflater.inflate(R.layout.contact_item, parent, false);
            }
        
            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                // 获取视图中的 TextView
                TextView nameTextView = view.findViewById(R.id.contactName);
                TextView phoneTextView = view.findViewById(R.id.contactPhone);
        
                // 从游标中提取数据
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        
                // 将数据绑定到 TextView
                nameTextView.setText(name);
                phoneTextView.setText(phone);
            }
        }
        
      • 启动类

        package com.example.cursoradapterexample;
        
        import androidx.appcompat.app.AppCompatActivity;
        import android.database.Cursor;
        import android.os.Bundle;
        import android.provider.ContactsContract;
        import android.widget.ListView;
        
        /**
         * 主活动,设置 ListView 并使用 CursorAdapter 绑定联系人数据。
         */
        public class MainActivity extends AppCompatActivity {
        
            private ContactsCursorAdapter adapter;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                // 获取 ListView 的引用
                ListView listView = findViewById(R.id.listView);
        
                // 查询联系人数据库中的所有联系人
                Cursor cursor = getContentResolver().query(
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null,
                        null,
                        null,
                        null
                );
        
                // 创建 ContactsCursorAdapter 并将其设置为 ListView 的适配器
                adapter = new ContactsCursorAdapter(this, cursor, 0);
                listView.setAdapter(adapter);
            }
        }
        

    显示内容提供者的数据

    • 场景描述:通过内容提供者从其他应用系统服务获取数据并展示。例如,显示系统日历中的事件媒体库中的图片

    • 示例从系统媒体库中显示图片

      • 自定义CursorAdapter类PhotosCursorAdapter.java

        package com.example.cursoradapterexample;
        
        import android.content.Context;
        import android.database.Cursor;
        import android.provider.MediaStore;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.CursorAdapter;
        import android.widget.ImageView;
        
        import com.squareup.picasso.Picasso;
        
        /**
         * 自定义 CursorAdapter,用于将图片数据从游标绑定到 ListView。
         */
        public class PhotosCursorAdapter extends CursorAdapter {
        
            public PhotosCursorAdapter(Context context, Cursor cursor, int flags) {
                super(context, cursor, flags);
            }
        
            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                // 使用自定义布局文件创建新视图
                LayoutInflater inflater = LayoutInflater.from(context);
                return inflater.inflate(R.layout.photo_item, parent, false);
            }
        
            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                // 获取视图中的 ImageView
                ImageView imageView = view.findViewById(R.id.photoImageView);
        
                // 从游标中提取图片路径
                String imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        
                // 使用第三方库加载图片(如 Picasso)
                Picasso.get().load("file://" + imagePath).into(imageView);
            }
        }
        
      • 启动类

        package com.example.cursoradapterexample;
        
        import androidx.appcompat.app.AppCompatActivity;
        import android.database.Cursor;
        import android.os.Bundle;
        import android.provider.MediaStore;
        import android.widget.ListView;
        
        /**
         * 主活动,设置 ListView 并使用 CursorAdapter 绑定图片数据。
         */
        public class MainActivity extends AppCompatActivity {
        
            private PhotosCursorAdapter adapter;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                // 获取 ListView 的引用
                ListView listView = findViewById(R.id.listView);
        
                // 查询媒体库中的所有图片
                Cursor cursor = getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        null,
                        null,
                        null,
                        null
                );
        
                // 创建 PhotosCursorAdapter 并将其设置为 ListView 的适配器
                adapter = new PhotosCursorAdapter(this, cursor, 0);
                listView.setAdapter(adapter);
            }
        }
        

    显示动态更新的数据

    • 场景描述:数据集频繁变化时,CursorAdapter 具有自动更新的特性。例如,展示动态变化的消息列表任务列表

    • 示例展示一个动态更新的任务列表

      • 自定义CursorAdapter类TasksCursorAdapter.java

        package com.example.cursoradapterexample;
        
        import android.content.Context;
        import android.database.Cursor;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.CursorAdapter;
        import android.widget.TextView;
        
        /**
         * 自定义 CursorAdapter,用于将任务数据从游标绑定到 ListView。
         */
        public class TasksCursorAdapter extends CursorAdapter {
        
            public TasksCursorAdapter(Context context, Cursor cursor, int flags) {
                super(context, cursor, flags);
            }
        
            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                // 使用自定义布局文件创建新视图
                LayoutInflater inflater = LayoutInflater.from(context);
                return inflater.inflate(R.layout.task_item, parent, false);
            }
        
            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                // 获取视图中的 TextView
                TextView taskTextView = view.findViewById(R.id.taskTextView);
        
                // 从游标中提取任务名称
                String taskName = cursor.getString(cursor.getColumnIndex("task_name"));
        
                // 将数据绑定到 TextView
                taskTextView.setText(taskName);
            }
        }
        
      • 启动类

        package com.example.cursoradapterexample;
        
        import androidx.appcompat.app.AppCompatActivity;
        import android.database.Cursor;
        import android.os.Bundle;
        import android.widget.ListView;
        
        /**
         * 主活动,设置 ListView 并使用 CursorAdapter 绑定任务数据。
         */
        public class MainActivity extends AppCompatActivity {
        
            private TasksCursorAdapter adapter;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                // 获取 ListView 的引用
                ListView listView = findViewById(R.id.listView);
        
                // 查询任务数据库中的所有任务
                Cursor cursor = getContentResolver().query(
                        TaskProvider.CONTENT_URI,
                        null,
                        null,
                        null,
                        null
                );
        
                // 创建 TasksCursorAdapter 并将其设置为 ListView 的适配器
                adapter = new TasksCursorAdapter(this, cursor, 0);
                listView.setAdapter(adapter);
            }
        }
        

    数据过滤和排序

    • 场景描述:通过对数据库查询结果进行过滤和排序,将数据展示给用户。例如,展示按日期排序的事件列表

    • 示例:在查询数据时对结果进行排序,然后通过 CursorAdapter 显示排序后的数据

      • 数据库查询

        Cursor cursor = getContentResolver().query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null,
                null,
                null,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"
        );
        

    总结

    • CursorAdapter 适用于以下场景

      • 显示数据库中的数据:如联系人列表消息记录任务清单
      • 显示内容提供者的数据:如系统日历事件媒体库图片
      • 动态更新的数据:如消息列表任务列表
      • 数据过滤和排序:如按特定条件排序的数据库结果展示
    • 它能够有效地将从数据库内容提供者中获取的数据动态地绑定到 UI 组件中,支持自动更新数据变化通知

完整代码示例

  • 首先需要在 AndroidManifest.xml添加访问数据库的权限

    <uses-permission android:name="android.permission.INTERNET"/>
    
  • 创建一个 SQLite 数据库,并添加一个表格来存储数据。创建一个名为DatabaseHelper.javaSQLiteOpenHelper 子类在其中进行操作

    package com.example.cursoradapterexample;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.content.ContentValues;
    
    /**
     * 辅助类,用于管理数据库的创建和版本管理。
     */
    public class DatabaseHelper extends SQLiteOpenHelper {
    
        // 数据库名称和版本
        private static final String DATABASE_NAME = "example.db";
        private static final int DATABASE_VERSION = 1;
    
        // 表名称和列名称
        public static final String TABLE_NAME = "items";
        public static final String COLUMN_ID = "_id";
        public static final String COLUMN_NAME = "name";
    
        // 创建表的 SQL 语句
        private static final String TABLE_CREATE =
                "CREATE TABLE " + TABLE_NAME + " (" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COLUMN_NAME + " TEXT NOT NULL);";
    
        // 构造函数
        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
        // 第一次创建数据库时调用
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(TABLE_CREATE); // 执行创建表的 SQL 语句
        }
    
        // 数据库升级时调用
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); // 删除旧表
            onCreate(db); // 重新创建表
        }
    
        // 插入示例数据的方法
        public void insertSampleData() {
            SQLiteDatabase db = getWritableDatabase();
            ContentValues values = new ContentValues();
            
            // 插入第一个条目
            values.put(COLUMN_NAME, "Item 1");
            db.insert(TABLE_NAME, null, values);
            
            // 插入第二个条目
            values.put(COLUMN_NAME, "Item 2");
            db.insert(TABLE_NAME, null, values);
            
            // 插入第三个条目
            values.put(COLUMN_NAME, "Item 3");
            db.insert(TABLE_NAME, null, values);
        }
    }
    
  • 创建一个名为MyCursorAdapter.java自定义 CursorAdapter 类来将数据绑定到 ListView

    package com.example.cursoradapterexample;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.CursorAdapter;
    import android.widget.TextView;
    
    /**
     * 自定义 CursorAdapter,用于将数据从游标绑定到 ListView。
     */
    public class MyCursorAdapter extends CursorAdapter {
    
        // 构造函数
        public MyCursorAdapter(Context context, Cursor cursor, int flags) {
            super(context, cursor, flags);
        }
    
        // 创建一个新视图用于每个列表项
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            // 使用 item_layout 布局文件创建新视图
            LayoutInflater inflater = LayoutInflater.from(context);
            return inflater.inflate(R.layout.item_layout, parent, false);
        }
    
        // 将数据从游标绑定到视图
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            // 获取布局文件中的 TextView
            TextView textView = view.findViewById(R.id.textView);
    
            // 从游标中提取数据
            String name = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.COLUMN_NAME));
    
            // 将数据绑定到 TextView
            textView.setText(name);
        }
    }
    
  • 创建布局文件res/layout/item_layout.xml用于展示每个列表项

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="16dp">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"/>
    </LinearLayout>
    
  • MainActivity 启动类中初始化数据库,插入示例数据,并将数据绑定到 ListView

    package com.example.cursoradapterexample;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.database.Cursor;
    import android.os.Bundle;
    import android.widget.ListView;
    
    /**
     * 主活动,设置 ListView 并使用 CursorAdapter 绑定数据。
     */
    public class MainActivity extends AppCompatActivity {
    
        private DatabaseHelper dbHelper;
        private MyCursorAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 初始化数据库辅助类并插入示例数据
            dbHelper = new DatabaseHelper(this);
            dbHelper.insertSampleData();
    
            // 获取 ListView 的引用
            ListView listView = findViewById(R.id.listView);
    
            // 查询数据库中的所有条目
            Cursor cursor = dbHelper.getReadableDatabase().query(
                    DatabaseHelper.TABLE_NAME,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null
            );
    
            // 创建一个新的 MyCursorAdapter 并将其设置为 ListView 的适配器
            adapter = new MyCursorAdapter(this, cursor, 0);
            listView.setAdapter(adapter);
        }
    }
    
  • 创建主活动的布局文件res/layout/activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </RelativeLayout>
    
  • 运行应该能看到一个列表,展示了从数据库中检索到的数据。这个示例中,我们创建了一个 SQLite 数据库,插入了一些示例数据,然后使用 CursorAdapter 将这些数据绑定到一个 ListView

posted @ 2024-07-31 20:14  阿俊学JAVA  阅读(118)  评论(0编辑  收藏  举报