使用 Expandablelistview android studio -sqlite 仅当 chlid 为 NOT NULL 时才显示 header

Display header only when chlid is NOT NULL using Expandablelistview android studio -sqlite

我正在尝试使用从 "Organ features" 列提取的 header 文本和从 pharynx 列提取的 child 文本制作一个可扩展列表视图,这是我的数据库结构:

Database structure

我希望器官特征显示为 header 只有当它们的 child 列表(= 来自咽柱的实例)不是 NULL 时。 这是我到目前为止得到的(如你所见,咽柱中的静脉引流是空的,但仍显示为 header,我不希望这样):

picture from the emulator

我想我应该添加一个语句“if(DATABASECHILD_1 != null)”或类似的东西..

感谢您的帮助!

Database.Java

package ma.ac.iav.learn;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;

public class Database {
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "URTdd.db";
    private static final String DATABASE_TABLE = "OrganAnatomy";
    public static final String DATABASE_ID = "_id";
    public static final String DATABASE_GROUP_1 = "Organ_features";
    public static final String DATABASE_CHILD_1 = "Pharynx";
    private final Context mContext;
    private DatabaseHelper mDatabaseHelper;
    private SQLiteDatabase mDB;

    public Database(Context context) {
        mContext = context;
    }

    public void open() {
        mDatabaseHelper = new DatabaseHelper(mContext, DATABASE_NAME, null, DATABASE_VERSION);
        mDB = mDatabaseHelper.getWritableDatabase();
    }


    public void close() {
        if (mDatabaseHelper != null) mDatabaseHelper.close();
    }

    public Cursor getDatabase() {
            return mDB.query(DATABASE_TABLE, null, null, null, null, null, DATABASE_GROUP_1);
    }

    public Cursor getID(long rowID) {
            return mDB.query(DATABASE_TABLE, null, "_id" + " = "
                + rowID, null, null, null, null);

    }

    public class DatabaseHelper extends SQLiteAssetHelper {

        public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);

        }
    }


}

MainActivity.java

package ma.ac.iav.learn;

import android.content.Context;
import android.database.Cursor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ExpandableListView;
import android.widget.SimpleCursorTreeAdapter;

public class MainActivity extends AppCompatActivity {
    ExpandableListView expandableListView;
    Database mDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
             /*
        "Called when the database has been opened."
        https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onOpen(android.database.sqlite.SQLiteDatabase)
         */
        mDatabase = new Database(this);
        mDatabase.open();

        /*
        "This interface provides random read-write access to the result set returned by a database query."
        https://developer.android.com/reference/android/database/Cursor.html
         */

        Cursor cursor = mDatabase.getDatabase();
        startManagingCursor(cursor);

        /*
        "A list of column names that will be used to display the data for a group."
        "The group views (from the group layouts) that should display column in the "from" parameter."
        "A list of column names that will be used to display the data for a child."
        "The resource identifier of a layout file that defines the views for a child."
        https://developer.android.com/reference/android/widget/SimpleCursorTreeAdapter.html#SimpleCursorTreeAdapter(android.content.Context, android.database.Cursor, int, java.lang.String[], int[], int, java.lang.String[], int[])
         */

        String[] groupFrom = {
                Database.DATABASE_GROUP_1,
        };

        int[] groupTo = {
                R.id.group1,
        };
        String[] childFrom = new String[]{
                Database.DATABASE_CHILD_1,
        };
        int[] childTo = {
                R.id.child1,
        };

        /*
        "An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file."
        https://developer.android.com/reference/android/widget/SimpleCursorTreeAdapter.html
        */
        SimpleCursorTreeAdapter simplecursortreeAdapter = new ExpandableListViewAdapter(
                this,
                cursor,
                R.layout.list_group,
                groupFrom,
                groupTo,
                R.layout.list_child,
                childFrom,
                childTo
        );

        /*
        "Finds a view that was identified by the android:id XML attribute that was processed in onCreate(Bundle)."
        "Sets the adapter that provides data to this view."
        https://developer.android.com/reference/android/app/Activity.html#findViewById(int)
        https://developer.android.com/reference/android/widget/ExpandableListView.html#setAdapter(android.widget.ExpandableListAdapter)
         */
        expandableListView = findViewById(R.id.expandableListview);
        expandableListView.setAdapter(simplecursortreeAdapter);

    }

    /*
    "Closes the Cursor, releasing all of its resources and making it completely invalid."
    https://developer.android.com/reference/android/database/Cursor.html#close()
     */
    protected void onDestroy() {
        super.onDestroy();
        mDatabase.close();
    }

    private class ExpandableListViewAdapter extends SimpleCursorTreeAdapter {
        private ExpandableListViewAdapter(
                Context context,
                Cursor cursor,
                int groupLayout,
                String[] groupFrom,
                int[] groupTo,
                int childLayout,
                String[] childFrom,
                int[] childTo) {
            super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
        }

        /*
        "Gets the Cursor for the children at the given group."
        https://developer.android.com/reference/android/widget/CursorTreeAdapter.html#getChildrenCursor(android.database.Cursor)
         */
        protected Cursor getChildrenCursor(Cursor groupCursor) {
            return mDatabase.getID(groupCursor.getInt(groupCursor.getColumnIndex(Database.DATABASE_ID)));
        }

    }
}

我相信你想要一个基于 :-

的查询
SELECT * FROM OrganAnatomy WHERE Pharynx IS NOT NULL ORDER BY Organ_features;

这将导致:-

要将其转换为 SQLiteDatabase query 方法使用,代码而不是 :-

    public Cursor getDatabase() {
        return mDB.query(DATABASE_TABLE, null, null, null, null, null, DATABASE_GROUP_1);
    }

可能是:-

    public Cursor getDatabase() {
        String whereclause = DATABASE_CHILD_1 + " IS NOT NULL";
        return mDB.query(DATABASE_TABLE, null, whereclause, null, null, null, DATABASE_GROUP_1);
    }
  • 请注意,以上代码是原理代码,尚未经过测试,因此可能存在一些错误。
  • 请注意,尚未尝试将其应用于 ExpanableListView,假定适配器会适当地处理 Cursor。
  • 没有这样的 IF 语句(IF ??? EXISTS/ NOT EXISTS 是您看到使用 IF 的地方),而是一个 WHERE 子句,它确定要包括哪些行(因此在这种情况下只包括Pharynx 列不为空的行)。
    • 真正等同于 IF 的是 CASE WHEN .... ELSE .... END AS 结构,虽然这不是必需的,也不适合这种情况。
    • 还有 HAVING 子句,但这需要一个 GROUP BY 子句并作用于结果而不是输入行,并且真正用于 post 处理,例如你可以有 SELECT * FROM OrganAnatomy GROUP BY _id HAVING Pharynx IS NOT NULL ORDER BY Organ_features; (因为 _id 是唯一的,所以每一行都在它自己的组中)。
    • 在这种情况下 overkill/over-complicated 使用 HAVING 子句。