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

1

0

I'm trying to make an expendable list view with the header text being extratced from column "Organ features" and child text is extratced from the pharynx column, this is my database structure:

Database structure

I want organ features to be displayed as header only if their childlist(= instances from the pharynx colum) are NOT NULL. This is what i got so far (as you see, the venous drainage is empty in pharynx column but still displayed as header, and i dont want that):

picture from the emulator

i Think i should add a statment " if(DATABASECHILD_1 != null)" or something like that ..

Thanks for the help!

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)));
        }

    }
}
Acatalectic answered 29/7, 2018 at 20:58 Comment(0)
S
0

I believe that you want a query based upon :-

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

This would result in :-

enter image description here

To convert this for use by the SQLiteDatabase query method, the code instead of being :-

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

could be :-

    public Cursor getDatabase() {
        String whereclause = DATABASE_CHILD_1 + " IS NOT NULL";
        return mDB.query(DATABASE_TABLE, null, whereclause, null, null, null, DATABASE_GROUP_1);
    }
  • Note the above code is in-principle code and has not been tested, so may contain some errors.
  • Note no attempt has been made to apply this to the ExpanableListView, it has been assumed that the adapter handles the Cursor appropriately.
  • There is no IF statement as such (IF ??? EXISTS/ NOT EXISTS is where you you see IF used), rather a WHERE clause, which determines what rows are to be included (so in this case only include rows WHERE the Pharynx column IS NOT NULL).
    • The real equivalent to IF is the CASE WHEN .... ELSE .... END AS construct, although this isn't needed and also isn't suitable for this scenario.
    • There is also the HAVING clause but this expects a GROUP BY clause and acts upon the result rather than the input rows and is really used for post processing, e.g. you could have SELECT * FROM OrganAnatomy GROUP BY _id HAVING Pharynx IS NOT NULL ORDER BY Organ_features; (works as _id will be unique so every row will be in it's own group).
    • Using the HAVING clause is overkill/over-complicated in this scenario.
Shipload answered 30/7, 2018 at 22:48 Comment(9)
Dude, i owe you so much! you can't image how much depressed i was before your answer! if you have ever been to morocco i'll be happy to invit you in, thank you so much! you should know that you made a huge favor to me!Acatalectic
Just two things: if i want to make two activities with expendablelistview but with different content (the first one uses a column with Not null statement and other one use another column but with nothing,) ..should i create two database classes ( i've done that and it workls perfectly but i don't know if there is another appropriate method)Acatalectic
the second question is: in each child view, there will be text and some images (number is variable from child to child). how can i adjust or do it? --i know it'll be long thing to explain ..i just need to direct me to what i should use ..as you did in your answer because you explain perfectly! Thanks again! even if you didn't answer those two question, you still a HERO to me!Acatalectic
1) Possibly use the same adapter but perhaps with a parameter passed to it to differentiate (so same cursor/layout could be used). 2) the typeOf(column_name) could be used to check if BLOB or not SQL As Understood By SQLite- Core FunctionsShipload
I'm so sorry but i didn't understand what you mean, i'm new to android so i don't know all the terms. what i have tried is i added picture in aother columns(larynx_pitcures), and i added pictures in correspondant cases(some cases are empty, and i only can add one picture per case) . i added imageview in child_list layout! .. this what i added in Database.java: DATABASE_CHILD_2 = "pictures";' then and this what i have changed in Mainactivity.java : String[] childFrom = new String[]{Database.DATABASE_CHILD_1, Database.DATABASE_CHILD_2}; int[] childTo = {R.id.child1, R.id.child2};Acatalectic
when i run it in emulator, the child view with no pictures works, but when i expand header with childview in which child has picture ..the app stopsAcatalectic
for your information , i have used one picture (PNG) and size 7KB! thanks a lot for the effortAcatalectic
@ErrahbiZouhair, really you should ask a new question(s) and if the issue is the app stops then you should include the stack-trace (if unsure about what a stack-trace is then look at Analyze a stack trace)Shipload
Okey Mike Thanks a lotAcatalectic

© 2022 - 2024 — McMap. All rights reserved.