使用 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 子句。
我正在尝试使用从 "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 子句。