notifyDataSetChanged() not refreshing expandable list view
Asked Answered
A

1

5

I am using Expandable ListView and the data in it is populated through Sqlite database. I have given an option to delete a group from ExpandableListView and it actually deletes the respective row in the database. But the activity doesn't gets refreshed and the deleted 'case' is visible until one goes back and comes again to this activity. I have created a class that extends *BaseExpandableListAdapter*. It contains all the overridden methods. Following is the code:

public class ExpandableListAdapterForRunning extends BaseExpandableListAdapter {

private Context _context;
private List<String> _listDataHeader; // header titles
public  static List<String> _listDate;
public int index;
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;

public ExpandableListAdapterForRunning(Context context, List<String> listDataHeader,
        HashMap<String, List<String>> listChildData,int i,List<String> listDate) {
     this._context = context;
    this._listDataHeader = listDataHeader;
    this._listDataChild = listChildData;
    this.index=i;
    this._listDate=listDate;
}

@Override
public Object getChild(int groupPosition, int childPosititon) {
    return this._listDataChild.get(this._listDataHeader.get(groupPosition))
            .get(childPosititon);
}

//other overridden methods
}    

Now there is another class RunningCase.java which extends Activity. This class is used to populate the data in ExpandableListView. OnLongClick() (tap and hold) of any group in ExpandableListView, a context menu appears. The context menu contains an option Delete to delete that case from the database and refresh the RunningCase activity.

    public class RunningCase extends Activity

    {
    String[] day;
    LinearLayout layout_MainMenu;
    Case cases;
    ExpandableListAdapterForRunning listAdapter;
    ExpandableListView expListView;
    List<String> listDataHeader;
    List<String> listDate;
     HashMap<String, List<String>> listDataChild;    
    Case date;

protected void onCreate(Bundle savedInstanceState) {
    prepareListData();     
    expListView=(ExpandableListView) findViewById(R.id.lvExp);
    listAdapter= new  ExpandableListAdapterForRunning(this,listDataHeader,listDataChild,i,listDate);
    expListView.setAdapter(listAdapter);
    registerForContextMenu(expListView);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add("Delete");
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    super.onContextItemSelected(item);
    final DatabaseHandler dbs = new DatabaseHandler(this);
    Cursor c = null;
    ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item
            .getMenuInfo();

    int type = ExpandableListView.getPackedPositionType(info.packedPosition);
    int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);

    if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
          String cp=(String) listAdapter.getChild(groupPosition, 0);
        caseno=cp.substring(11, cp.length());       
        }

    if(item.getTitle()=="Delete")
    {       
        dbs.deletecase(caseno);
        expListView.post(new Runnable() {
            public void run() {
            listAdapter.notifyDataSetChanged();  //this is not working
            }
        });
        Toast.makeText(this, "The Case has been Deleted.", Toast.LENGTH_LONG).show();
    }
 return true;
}
//this is the method to populate the expandableListView
public void prepareListData() {
    listDataHeader = new ArrayList<String>();
    listDate =new ArrayList<String>();
    listDataChild = new HashMap<String, List<String>>();
    final DatabaseHandler db = new DatabaseHandler(this);
    List<Case> cases = db.getRunning();       
    int i=0;
    for (Case cn : cases) {
        String str = cn.getPetitioner()+" V/S " + cn.getDefendant();
        String caseNo=cn.getCaseNumber();
        String caseStage=cn.getCaseStage();
        String caseName=cn.getCourtName();
        listDataHeader.add(str);
        List<String> case2 = new ArrayList<String>();
        case2.add("Case No. : "+caseNo);
        case2.add("Court Name :"+caseName);
        case2.add("Case Stage :"+caseStage);

        listDataChild.put(listDataHeader.get(i++), case2);

    }
       List<Date> date = db.getRunning_child();       
       for (Date cn : date) {
           String str = cn.getNextDate();
           listDate.add(str);
    }
}

The methods db.getRunning(), db.getRunning_child() retrieve data from database. Also, the following is the code to delete the case from database which is working perfectly:

void deletecase(String casenum){
    SQLiteDatabase db = this.getWritableDatabase();
    String whereClause = "Case_number = ?";
    String[] whereArgs = new String[] {
            casenum
        };

    db.delete(TABLE_CASEINFO,whereClause,whereArgs);        
    db.delete(TABLE_CLIENTINFO,whereClause,whereArgs);      
    db.delete(TABLE_DATEINFO,whereClause,whereArgs);        
        Log.d("case deleted","casenum: "+casenum); 

    db.close(); // Closing database connection      
}

Please help me out. The activity should get refreshed on deleting a case so that the deleted case no more appears. Thanks in advance!!

Acidulate answered 14/3, 2014 at 12:36 Comment(2)
you remove the entry from DB but you don't remove it from list. you should modify your long click routineFrisky
How should i remove it from the list? Can you please help me with the codeAcidulate
R
4

Before calling notfifyDataSetChanged you should update your data which are private HashMap> _listDataChild by setData method which is created by you on your adapter. First set data, then notify.

Example:

public class MyAdapter extends BaseAdapter {

public MyAdapter(...) {
    super(...);
}

@Override
public View getView(int position, View view, ViewGroup parent) {
    .....
    return view;

}

private void setData() {
    ...
   notifyDataSetChanged();
}
}
Rede answered 14/3, 2014 at 12:44 Comment(4)
That means I should call the method prepareListData() before calling notifyDataSetChanged() ?Acidulate
@Acidulate I don't think so. You should update the data in your adapter. When the first time you create your adapter instance, you send some data to your adapter by constructor. prepareListData() can't update it.Rede
Thanks @MSr. I added the following lines before calling notifyDataSetChanged() and it worked: listDataHeader.remove(groupPosition); listDate.remove(groupPosition); for(int j=0;j<listDataHeader.size();j++) listDataChild.remove(listDataHeader.get(j));Acidulate
Adding the above lines of code works for the first time. But as I delete another case continuously then there occurs a NullPoiinterException at getChildPosition() under getChild() method of ExpandableListAdapterForRunning.java. Please tell me where am I going wrongAcidulate

© 2022 - 2024 — McMap. All rights reserved.