Android 在两个不同的列表视图中显示光标结果 Activity

Android Display Cursor Result In Two Different Listview In One Activity

知道如何在同一个 activity 中的两个不同列表视图中显示光标结果吗?一个例子来自 Whatsapp,他们有(我假设)"Chats" table 和 "Messages" table。一旦我们在工具栏上键入关键字,我将查询两个 table 并在 1 activity 中的两个不同列表视图中显示。有什么办法吗?或者它们只显示在 1 个列表视图中?请指教。

谢谢。

是的,这是可以做到的。为了以简单的方式模仿上述内容,假设数据库有两个 tables 聊天和消息。它们都有两列,一个唯一标识符和一个文本列。

使用 SQLiteOpenHelper 的子class,我们可以得到一个名为 DBHlpr.java 的文件:-

public class DBHlpr extends SQLiteOpenHelper {

    static final String DBNAME = "mydb";
    static final String CHATTABLE = "chats";
    static final String MSGTABLE = "messages";

    static final String TEXTCOL = "textdata";
    static final String IDCOL = "_id";


    DBHlpr(Context context) {
        super(context,DBNAME,null,1);
    }

    public void onCreate(SQLiteDatabase db){
        db.execSQL("CREATE TABLE " + CHATTABLE + " (" + IDCOL + " INTEGER PRIMARY KEY, " + TEXTCOL + " TEXT)");
        db.execSQL("CREATE TABLE " + MSGTABLE + " (" + IDCOL + " INTEGER PRIMARY KEY, " + TEXTCOL + " TEXT)");
    }

    public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {
    }

    public void insertRow(String table, String text) {
        ContentValues cv = new ContentValues();
        cv.put(TEXTCOL,text);
         long id = this.getWritableDatabase().insert(table,null,cv);
        Log.d("DBHLP-INSRT","Added row with ID=" + Long.toString(id));
    }

    public Cursor getRows(String table, String srchstr) {

        SQLiteDatabase db = getWritableDatabase();

        String whereclause = null;
        if (srchstr.length() > 0) {
            whereclause = TEXTCOL + " LIKE '%" + srchstr + "%' ";
        }
         return db.query(
                table,
                null,whereclause,null,null,null,null);
    }
}

onCreate 方法将创建 2 个 table,即 chatsmessages(根据 CHATTABLE和 MSGTABLE)。

onUpgrade is required but does nothing as yet.

insertRow 可用于向 table 添加一行(因为它们具有相同的结构)。请注意,它将写入日志,以便可以轻松确认插入。

getRows用于获取包含数据的Cursor(来自数据库的数据)。同样,这一个方法可以用于两个 tables。它传递一个字符串,用于(如果它的长度大于 0)过滤 tables(根据在搜索字段中输入的数据)。

activity 将需要指定两个 ListView 的布局,在本例中它将是 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.so45787986.MainActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Search" />
    <EditText
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Chats" />
    <ListView
        android:id="@+id/chats"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </ListView>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Messages" />
    <ListView
        android:id="@+id/messages"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </ListView>
</LinearLayout>

没有什么特别的,它是一个非常简单的布局,一个用于搜索条件的 EditText 一个用于聊天列表标题的 TextView(以下 ListView),然后是另一个用于消息的 TextView 和 ListView。

MainActivity.java 可能是:-

public class MainActivity extends AppCompatActivity {

    DBHlpr dbhlpr = new DBHlpr(this);
    Cursor chatcursor;
    Cursor msgcursor;
    TextWatcher tx;
    EditText search;
    ListView chatlist;
    ListView msglist;
    SimpleCursorAdapter chat_sca;
    SimpleCursorAdapter msg_sca;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        search = (EditText) findViewById(R.id.search);
        chatlist = (ListView) findViewById(R.id.chats);
        msglist =  (ListView) findViewById(R.id.messages);


        // Add some data for testing

        dbhlpr.insertRow(DBHlpr.CHATTABLE, "This is my first chat");
        dbhlpr.insertRow(DBHlpr.CHATTABLE, "This is my second chat");
        dbhlpr.insertRow(DBHlpr.CHATTABLE, "This is my third chat");
        dbhlpr.insertRow(DBHlpr.MSGTABLE, "First Message");
        dbhlpr.insertRow(DBHlpr.MSGTABLE, "Second Message");
        dbhlpr.insertRow(DBHlpr.MSGTABLE, "Third Message");

        chatcursor = dbhlpr.getRows(DBHlpr.CHATTABLE,"");
        chat_sca = new SimpleCursorAdapter(
                this,
                android.R.layout.simple_list_item_1,
                chatcursor,
                new String[]{DBHlpr.TEXTCOL},
                new int[]{android.R.id.text1},
                0
                );
        chatlist.setAdapter(chat_sca);
        msgcursor = dbhlpr.getRows(DBHlpr.MSGTABLE,"");
        msg_sca = new SimpleCursorAdapter(
                this,
                android.R.layout.simple_list_item_1,
                msgcursor,
                new String[]{DBHlpr.TEXTCOL},
                new int[]{android.R.id.text1},
                0
        );
        msglist.setAdapter(msg_sca);

        search.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                refreshCursors();
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }

    private void refreshCursors() {
        chatcursor = dbhlpr.getRows(DBHlpr.CHATTABLE,search.getText().toString());
        chat_sca.swapCursor(chatcursor);
        msgcursor = dbhlpr.getRows(DBHlpr.MSGTABLE,search.getText().toString());
        msg_sca.swapCursor(msgcursor);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        chatcursor.close();
        msgcursor.close();
    }
}

首先定义了一些class变量:-

    DBHlpr dbhlpr = new DBHlpr(this);
    Cursor chatcursor;
    Cursor msgcursor;

与数据库相关。第一个创建 DBHlpr 的实例,另外两个用于 2 个游标(聊天和消息)。

TextWatcher tx;
EditText search;
ListView chatlist;
ListView msglist;

用于处理视图。 TextWatcher 用于检测搜索的变化。

    SimpleCursorAdapter chat_sca;
    SimpleCursorAdapter msg_sca;

用于使数据库数据适应 ListView。顾名思义,这些都是非常基本的,但可以用于演示目的。

onCreate 中的前 5 行非常标准。

接下来的 6 行基本相同,即 dbhlpr.insertRow(DBHlpr.CHATTABLE, "This is my first chat"); 并调用 insertRow 方法传递相应的 table 和要存储的数据。应该注意的是,第一次是 运行 是创建数据库的时间。请注意,这些行仅用于提供一些测试数据。

然后我们来到(注意下面的代码基本上是重复的,但是对于消息table):-

    chatcursor = dbhlpr.getRows(DBHlpr.CHATTABLE,"");
    chat_sca = new SimpleCursorAdapter(
            this,
            android.R.layout.simple_list_item_1,
            chatcursor,
            new String[]{DBHlpr.TEXTCOL},
            new int[]{android.R.id.text1},
            0
            );
    chatlist.setAdapter(chat_sca);

第一行获取带有相应数据的游标(所有聊天行,根据第二个参数)。 第 2-9 行是设置简单游标适配器的单个命令(第 1 个参数是上下文,第 2 个要使用的布局(我们欺骗并使用一个简单的),第 3 个是保存数据的游标,第 4 个是要获取游标中数据的列,第 5 位是放置数据的视图 ID,第 6 位应为 0)。 最后一行告诉 ListView 使用适配器。

随后将 TextWatcher 添加到搜索中。在此使用 onTextChanged 方法,它调用 refreshCursors 方法。

refreshCursors 方法使用更改后的搜索数据从数据库中获取数据到现有游标中,然后通过 swapCursor 告诉适配器数据已更改。

最后onDestroy方法用于在Activity即将结束时关闭游标。

最初 运行 :-

在搜索字段中输入 f 后:-