prabhakaran
prabhakaran

Reputation: 678

IndexOutOfBoundException in ExpandableListView

I found a lot of question about this problem, but I can't fix it. I have spend a whole day i couldn't solve. I rechecked my for loop also

If i have parent value 7 if i click on 4th parent its expands and again i click on 2nd parent its expends and working fine. but if i click 5th or 6th or 7th parent i am getting this error.. i don't know where i am wrong in my code..

LogCat :

07-12 11:56:24.504: E/AndroidRuntime(3548): FATAL EXCEPTION: main
07-12 11:56:24.504: E/AndroidRuntime(3548): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
07-12 11:56:24.504: E/AndroidRuntime(3548):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at java.util.ArrayList.add(ArrayList.java:143)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.widget.ExpandableListConnector.expandGroup(ExpandableListConnector.java:685)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.widget.ExpandableListView.handleItemClick(ExpandableListView.java:562)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.widget.ExpandableListView.performItemClick(ExpandableListView.java:522)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2812)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.widget.AbsListView$1.run(AbsListView.java:3571)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.os.Handler.handleCallback(Handler.java:725)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.os.Looper.loop(Looper.java:153)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at android.app.ActivityThread.main(ActivityThread.java:5297)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at java.lang.reflect.Method.invokeNative(Native Method)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at java.lang.reflect.Method.invoke(Method.java:511)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
07-12 11:56:24.504: E/AndroidRuntime(3548):     at dalvik.system.NativeStart.main(Native Method)

Java

mAdapter = new MyExpandableListAdapter(MainActivity.this, listchapt,
                null);

        elvForDialog.setIndicatorBounds(width - 20, width);// 130
        elvForDialog.setAdapter(mAdapter);

        elvForDialog.setOnGroupClickListener(new OnGroupClickListener() {

            public boolean onGroupClick(ExpandableListView arg0, View arg1,
                    int arg2, long arg3) throws RuntimeException {
                String pos = (String)mAdapter.getGroup(arg2);
                System.out.println("position" + pos);
                List<String> children = new ArrayList<String>();
                children.clear();
                listNames.clear();
                for (int i = 0; i < listchapt.size(); i++) {

                    dbHelper.openDataBase();
                    children = dbHelper.GetSubchapt(pos);
                    dbHelper.close();
                    listNames.add(children);  // line no.143
                }

                System.out.println("position" + pos);
                Display newDisplay = getWindowManager().getDefaultDisplay();
                int width = newDisplay.getWidth();
                mAdapter = new MyExpandableListAdapter(MainActivity.this,
                        listchapt, listNames);
                elvForDialog.setIndicatorBounds(width - 20, width);// 130
                elvForDialog.setAdapter(mAdapter);
                System.out.println("explist" + listSubchapt);

                try {

                    Log.v("LH", "ssetOnGroupClickListener");
                    Log.v("LH", "" + viewListLastSelected.toString());
                    Log.v("LH",
                            "" + ((TextView) viewListLastSelected).getText());

                } catch (Exception e) {
                    Log.v("LH", "ERROR@onCreate: " + e.toString());
                }
                return false;
            }
        });

        elvForDialog.setOnChildClickListener(new OnChildClickListener() {

            public boolean onChildClick(ExpandableListView arg0, View arg1,
                    int arg2, int arg3, long arg4) throws RuntimeException {

                currentChapt = listchapt.get(arg2).toString();
                currentSubchapt = listNames.get(arg2).get(arg3).toString();
                System.out.println("Yes it shows child " + currentChapt
                        + currentSubchapt);
                // createExpandableListViewDialog(1);

                Intent in = new Intent(MainActivity.this, WebContent.class);
                in.putExtra("chapterid", currentChapt);
                in.putExtra("subchaptid", currentSubchapt);
                startActivity(in);

                elvForDialog.clearChildFocus(viewListLastSelected);

                try {

                    viewListLastSelected.setBackgroundDrawable(null);
                    ((TextView) viewListLastSelected).setTextColor(Color.GRAY);
                } catch (Exception e) {
                }
                ((TextView) arg1).setTextColor(Color.WHITE);
                viewListLastSelected = arg1;

                return false;
            }
        });

        elvForDialog.setOnGroupExpandListener(new OnGroupExpandListener() {

            public void onGroupExpand(int groupPosition) {
                int len = mAdapter.getGroupCount();

                for (int i = 0; i < len; i++) {
                    if (i != groupPosition) {
                        elvForDialog.collapseGroup(i);
                    }
                }
            }

        });

MyAdapter class

public class MyExpandableListAdapter extends BaseExpandableListAdapter {
    Activity activity;
    List<String> listGroup = new ArrayList<String>();
    List<List<String>> listChild = new ArrayList<List<String>>();

    private int _posGroup = 0;
    private int _posChild = 0;



    public MyExpandableListAdapter(Activity a, List<String> group, List<List<String>> children){
        super();
        activity = a;
        listGroup = group;
        listChild = children;
    }


    public Object getChild(int groupPosition, int childPosition) {
        return listChild.get(groupPosition).get(childPosition);
    }


    public long getChildId(int groupPosition, int childPosition) {
        //Log.v("LH", "ChildID: " + childPosition);      
        _posGroup = groupPosition;
        _posChild = childPosition;
        return childPosition;
    }


    public int getChildrenCount(int groupPosition) {
        return listChild.get(groupPosition).size();    //line no 51
    }


    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {      
        String string = listChild.get(groupPosition).get(childPosition);
        View view = getGenericChildView(string);

        TextView text = (TextView) view;
        if(this._posGroup==groupPosition &&
                   this._posChild==childPosition)         
                {
                    text.setTextColor(Color.rgb(85, 85, 85));
                    text.setTypeface(null, Typeface.BOLD);
                }
       view.setBackgroundResource(R.drawable.menu_submenubg);

        return view;
    }


    //group method stub

    public Object getGroup(int groupPosition) {
        return listGroup.get(groupPosition);
    }

    public int getGroupCount() {
        return listGroup.size();
    }


    public long getGroupId(int groupPosition) {
        //Log.v("LH", "GroupID: " + groupPosition);
        return groupPosition;
    }


    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {      
        String string = listGroup.get(groupPosition);
        View result=getGenericGroupView(string);
        result.setBackgroundResource(R.drawable.menu_hoverbg);
        return result;
    }

    public TextView getGenericChildView(String s) {
        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT, 0);
        lp.height=73; //73,50
        TextView text = new TextView(activity);
        text.setLayoutParams(lp);
        text.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        text.setPadding(50, 0, 0, 0);
        text.setTextColor(Color.rgb(85, 85, 85));
        text.setTypeface(null, Typeface.BOLD);
        text.setTextSize(15);
        text.setText(s);
        return text;
    }


    public TextView getGenericGroupView(String s) {
        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT, 0);
        lp.height=60;
        TextView text = new TextView(activity);
        text.setLayoutParams(lp);
        text.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        text.setPadding(20, 0, 0, 0);
        text.setTextSize(20);
        text.setTextColor(Color.WHITE);      
        text.setText(s);
        return text;
    }


    public boolean hasStableIds() {      
        return false;
    }


    public boolean isChildSelectable(int groupPosition, int childPosition) {      
        return true;
    } 

Thank in advance..

Edit : DBHelper

public class DBHelper extends SQLiteOpenHelper {
    public int GetCursor;
    private Context myContext;
    public String DB_PATH = "data/data/com.redcaso.mia/databases/"; // path

    public static String DB_NAME = "Test.sqlite";// your database name
    static String ASSETS_DB_FOLDER = "db";
    private SQLiteDatabase db;

    public DBHelper(Context context) {
        super(context, DB_NAME, null, 2);
        if (db != null && db.isOpen())
            close();

        this.myContext = context;
        //DB_NAME = db_name;

        try {
            createDataBase();
            openDataBase();
        } catch (IOException e) {
            // System.out.println("Exception in creation of database : "+
            // e.getMessage());
            e.printStackTrace();
        }

    }



    public void createDataBase() throws IOException {
        boolean dbExist = checkDataBase();

        if (dbExist) {
            // System.out.println("Database Exist");
        } else {
            this.getReadableDatabase();

            try {
                copyDatabase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private void copyDatabase() throws IOException {
        InputStream input = myContext.getAssets().open(DB_NAME);
        String outputFileName = DB_PATH + DB_NAME;
        OutputStream output = new FileOutputStream(outputFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }

        // Close the streams
        output.flush();
        output.close();
        input.close();
        // System.out.println(DB_NAME + "Database Copied !");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public void openDataBase() throws SQLException {
        // Open the database
        String myPath = DB_PATH + DB_NAME;
        db = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
    }

    public boolean isOpen() {
        if (db != null)
            return db.isOpen();
        return false;
    }

    @Override
    public synchronized void close() {
        if (db != null)
            db.close();
        super.close();
    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDB = null;
        try {
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READWRITE);

        } catch (Exception e) {
            // database does't exist yet.
        }

        if (checkDB != null) {
            checkDB.close();
        }

        return checkDB != null ? true : false;
    }

    public Cursor execCursorQuery(String sql) {
        Cursor cursor = null;
        try {
            cursor = db.rawQuery(sql, null);
            GetCursor = cursor.getCount();
            Log.i("Inside execCursorQuery try", sql);
        } catch (Exception e) {
            Log.i("Inside execCursorQuery exception", e.getMessage());
        }
        return cursor;
    }

    public void execNonQuery(String sql) {
        try {
            db.execSQL(sql);
            // Log.d("SQL", sql);
        } catch (Exception e) {
            // Log.e("Err", e.getMessage());
        } finally {
            // closeDb();
        }
    }

    public ArrayList<String> GetchapterID(){
        String sql="";
            //System.out.println("Inside Database");
            sql="select distinct(ChapterId) from contents";

        ArrayList<String> list = new ArrayList<String>();
        Cursor cursor=db.rawQuery(sql, null);

        try{
        if(cursor != null){
        if (cursor.moveToFirst()) {
            do {
                list.add(cursor.getString(0));
            }
            while (cursor.moveToNext());
        }
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
        }
     else
            Toast.makeText(myContext, "No values in DB", Toast.LENGTH_SHORT).show();
        }
        catch(Exception e){
            System.out.println("GetGradeNames(): " +e);
        }
        return list;
    }
    public ArrayList<String> GetSubchapt(String type){
        String sql="";
            sql="select distinct(SubchapterId) from contents where ChapterId='"+type+"'";

        ArrayList<String> list = new ArrayList<String>();
        Cursor cursor=db.rawQuery(sql, null);

        try{
        if(cursor != null){
        if (cursor.moveToFirst()) {
            do {
                list.add(cursor.getString(0));
            }
            while (cursor.moveToNext());
        }
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
        }
     else
            Toast.makeText(myContext, "No Property in DB", Toast.LENGTH_SHORT).show();
        }
        catch(Exception e){
            System.out.println("GetLevelNames(): " +e);
        }
        return list;
    }
    public ArrayList<String> GetName(String chapter,String subchapt){
        String sql="";
            sql="select distinct(filename) from contents where SubchapterId='"+subchapt+"' and ChapterId='"+chapter+"'";

        ArrayList<String> list = new ArrayList<String>();
        Cursor cursor=db.rawQuery(sql, null);
        //list.add("All Topics - Entire "+grade);
        try{
        if(cursor != null){
        if (cursor.moveToFirst()) {
            do {
                list.add(cursor.getString(0));
            }
            while (cursor.moveToNext());
        }
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
        }
     else
            Toast.makeText(myContext, "No Address in DB", Toast.LENGTH_SHORT).show();
        }
        catch(Exception e){
            //System.out.println("GetBasicTopicNames(): " +e);
        }
        return list;
    }

Upvotes: 0

Views: 2173

Answers (2)

ADSL
ADSL

Reputation: 1

So your problem is in your onGroupClick. Here the return value is false means the click event is not handled, so it's normal that you found nothing in your log, cuz the expandGroup has been called in the SDK.

Try to return a true value in onGroupClick and handle collapse / expand yourself.

 public boolean onGroupClick(ExpandableListView arg0, View arg1,
                int arg2, long arg3) throws RuntimeException {
            String pos = (String)mAdapter.getGroup(arg2);
            System.out.println("position" + pos);
            List<String> children = new ArrayList<String>();
            children.clear();
            listNames.clear();
            for (int i = 0; i < listchapt.size(); i++) {

                dbHelper.openDataBase();
                children = dbHelper.GetSubchapt(pos);
                dbHelper.close();
                listNames.add(children);  // line no.143
            }

            System.out.println("position" + pos);
            Display newDisplay = getWindowManager().getDefaultDisplay();
            int width = newDisplay.getWidth();
            mAdapter = new MyExpandableListAdapter(MainActivity.this,
                    listchapt, listNames);
            elvForDialog.setIndicatorBounds(width - 20, width);// 130
            elvForDialog.setAdapter(mAdapter);
            System.out.println("explist" + listSubchapt);

            try {

                Log.v("LH", "ssetOnGroupClickListener");
                Log.v("LH", "" + viewListLastSelected.toString());
                Log.v("LH",
                        "" + ((TextView) viewListLastSelected).getText());

            } catch (Exception e) {
                Log.v("LH", "ERROR@onCreate: " + e.toString());
            }

            if (elvForDialog.isGroupExpanded(arg2))
                elvForDialog.collapseGroup(arg2);
            else
                elvForDialog.expandGroup(arg2);

            return true;
        }
    });

Upvotes: 0

Simas
Simas

Reputation: 44118

You are storing your children wrong and you don't have to re-create your adapter every time you add new children.

Here are some fixes to get your code functional:

Change your adapters constructor to, so it receives only activity and groups:

public MyExpandableListAdapter(Activity a, List<String> group){
    this.activity = a;
    this.listGroup = group;
}

Change the type of your children list, so you can access them by groupPosition, like this:

SparseArray<List<String>> listChild = new SparseArray<List<String>>();

Now create a new method inside the adapter which adds children:

public addChildren(int groupPosition, List<String> children) {
    this.listChild.put(groupPosition, children);
}

Now that the adapter is taken care of, fix your OnGroupClick event. Instead of setting a new adapter each time, add or remove the children (based on whether the children already exist):

expList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
    @Override
    public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
        if (mAdapter.getChildrenCount == 0) {
            dbHelper.openDataBase();
            children = dbHelper.GetSubchapt(pos);
            dbHelper.close();
            mAdapter.addChildren(groupPosition, children);
        }
        else
            mAdapter.removeChildren(groupPosition);
        return false;
    }
});

GroupClick event has been fixed now. What's left is to adjust your getChildrenCount method so it wouldn't throw a NPE:

public int getChildrenCount(int groupPosition) {
    if (listChild.get(groupPosition) == null) {
        Log.e("mAdapter.getChildrenCount", "Tried to access group's "+
        groupPosition+" children which have not yet been added!");
        return 0;
    }
    else  
        return listChild.get(groupPosition).size();
}

Post any further errors that might occur, as this code is not tested with your setup.

Upvotes: 2

Related Questions