Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically create groups and childs in expandable listview from json in android?

I am working on a client-server project in Android. I need to parse JSON from a given URL and place it in an ExpandableListView. In JSON response I am getting data with nodes containing arrays. So, I have to place main JsonArray to Groups in ExpandableListView. It works fine.

I can find out how many groups are coming in from the JSON but the problem arises when I am trying to place child inside each group based on the data coming from the server. My code only places the first child inside first group, but when I click on second child, it shows error.

I need to place "ID" and "username" inside respective group(e.g: email, fax, upload). My code can place one child info inside one group, but when I click second group, it crashes. Any kind of help will be highly appreciated.

So, my query is, how do I dynamically create groups and place child data inside each child based on server data?

Here is the error in log:

04-07 17:49:02.194: E/AndroidRuntime(13285): FATAL EXCEPTION: main
04-07 17:49:02.194: E/AndroidRuntime(13285): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.util.ArrayList.get(ArrayList.java:304)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.SimpleExpandableListAdapter.getChildrenCount(SimpleExpandableListAdapter.java:255)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListConnector.refreshExpGroupMetadataList(ExpandableListConnector.java:561)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListConnector.expandGroup(ExpandableListConnector.java:682)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListView.handleItemClick(ExpandableListView.java:561)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListView.performItemClick(ExpandableListView.java:521)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.AbsListView$PerformClick.run(AbsListView.java:2514)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.AbsListView$1.run(AbsListView.java:3168)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Handler.handleCallback(Handler.java:605)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Looper.loop(Looper.java:137)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.app.ActivityThread.main(ActivityThread.java:4424)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.lang.reflect.Method.invokeNative(Native Method)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.lang.reflect.Method.invoke(Method.java:511)

JSON response

{   "email":[   
    {"ID":"123","username":"dipakadmin"},
    {"ID":"3233","username":"raju"},
    {"ID":"5445","username":"hussain"}
    ]
,
"fax":[ 
    {"ID":"6665","username":"mohammad"},
    {"ID":"9877","username":"raj"},
    {"ID":"87655","username":"aryan"}
    ]
,
"upload":
    [   
    {"ID":"132322","username":"raja"},
    {"ID":"544333","username":"bala"},
    ]
}

This is just an example of JSON response. Real responses have many tags.

Code sample for ExpandableListActivity is below:

package com.ExpandableListActivity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ExpandableListActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;

public class DocumentCenter extends ExpandableListActivity {

    public static JSONObject  jsonDocu=null;
    JSONArray jArray = null;
    JSONObject json_data = null;
    JSONObject root = null;

    List<List<Map<String, String>>> childs;

    List<Map<String, String>> child1;
    List<Map<String, String>> child2;
    List<Map<String, String>> child3;
    SimpleExpandableListAdapter adapter;

    Map<String, String> childdata1;

    public static String url3=null;
    String strEmailNull=null;
    String strFaxNull=null;
    String strUploadNull=null;
    public String user=null;
    TextView txtMLSID;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main2);

        user= TabBarExample.getJsonUser;
        Log.e("log_tag","USERNAME On Document : "+user); 

        List<Map<String, String>> groups = new ArrayList<Map<String, String>>();

        child1 = new ArrayList<Map<String, String>>();
        child2 = new ArrayList<Map<String, String>>();
        child3 = new ArrayList<Map<String, String>>();  

        url3 ="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        Log.e("log_tag","URL on DOCUMENT : "+url3); 
        try {
            jsonDocu = JSONfunctions1.getJSONfromURL(url3);
            JSONArray ary = jsonDocu.names();

            Log.e("log_tag","ary : "+ary .toString()); 

            for (int i1 = 0; i1 < ary.length(); i1++) {
                String value =      ary.get(i1).toString();
                Log.e("log_tag","value : "+value); 
                strEmailNull=   jsonDocu.getString(value);
                if (!strEmailNull.equals("null")){
                    try{
                        Map<String, String> group1 = new HashMap<String, String>();
                        group1.put("group", value);
                        //group1.put("group", value+(i1+1));
                        groups.add(group1);

                        JSONArray  email = jsonDocu.getJSONArray(value);
                        for(int i=0;i<email.length() ;i++){                     
                            childdata1 = new HashMap<String, String>();

                            JSONObject e = email.getJSONObject(i+1);
                            childdata1.put("child", e.getString("ID"));
                            childdata1.put("child1",  "Name:  "+e.getString("name"));
                            childdata1.put("child2", "Size:  "+e.getString("size"));
                            childdata1.put("child3",  "Update:  "+e.getString("lastUpdate"));

                            child1.add(childdata1); 
                            childs = new ArrayList<List<Map<String, String>>>();
                        }
                    }catch(JSONException e){
                        Log.e("log_tag", "Error parsing data "+e.toString());
                    }
                }
            }
            childs.add(child1);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        adapter = new SimpleExpandableListAdapter(
            this, groups, R.layout.groups2, new String[] { "group" },
            new int[] { R.id.group }, childs, R.layout.childs2,
            new String[] { "child1","child2" ,"child3"}, new int[] { R.id.child1, R.id.child2, R.id.child3});
        setListAdapter(adapter);
    }

    @Override
    public boolean setSelectedChild(int groupPosition, int childPosition,
        boolean shouldExpandGroup) {
        //do something
        Log.e("log_tag","setSelectedChild: "); 
        return super.setSelectedChild(groupPosition, childPosition,
            shouldExpandGroup);
    }

    @Override
    public void setSelectedGroup(int groupPosition) {
        //do something

        Log.e("log_tag","setSelectedGroup: "); 
        super.setSelectedGroup(groupPosition);
    }
}
like image 520
mH16 Avatar asked Apr 07 '12 13:04

mH16


1 Answers

Here's how I would do it. Ofcourse you can use parse like you are parsing. But, I would use jackson library and create an object classes based on the response and use ObjectMapper which would look more elegant and it saves your time of parsing. You can add more fields here according to your need like inner Fax and Email classes and list:

public class ResponseObject {

private List<Email> email;

/**
 * @return the email
 */
public List<Email> getEmail() {
    return email;
}

/**
 * @param email
 *            the email to set
 */
public void setEmail(List<Email> email) {
    this.email = email;
}

public static class Email {
    private Integer ID;
    private String username;

    /**
     * @return the ID
     */
    public Integer getID() {
        return ID;
    }

    /**
     * @param ID
     *            the ID to set
     */
    public void setID(Integer ID) {
        ID = ID;
    }

    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }

    /**
     * @param username
     *            the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }
}
}

And then use BaseExpandableListAdapter like this, make changes and add views according to your need:

import java.util.ArrayList;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;

public class ResponseAdapter extends BaseExpandableListAdapter {
private ArrayList<ResponseObject> responseList = new ArrayList<ResponseObject>();

public ResponseAdapter(ArrayList<ResponseObject> responseObject) {
    this.responseList = responseObject;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getChildView(int groupPosition, int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {
    int ID = responseList.get(groupPosition).getEmail().get(childPosition)
            .getID();
    String username = responseList.get(groupPosition).getEmail()
            .get(childPosition).getUsername();
    return null;
}

@Override
public int getChildrenCount(int groupPosition) {
    return responseList.get(groupPosition).getEmail().size();
}

@Override
public Object getGroup(int groupPosition) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int getGroupCount() {
    return responseList.size();
}

@Override
public long getGroupId(int groupPosition) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View parent, ViewGroup viewGroup) {
    // Email group goes here
    return null;
}

@Override
public boolean hasStableIds() {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean isChildSelectable(int arg0, int arg1) {
    // TODO Auto-generated method stub
    return false;
}

}
like image 200
Milan Avatar answered Nov 14 '22 23:11

Milan