javaandroidexpandablelistviewexpandablelistadapter

Populate ExpandableListView using data from JSON response


I am having a problem with the expandablelistview. All the tutorials I've seen regarding the parent item have only one item. In my case I'm doing with multiple fields (name and comment) in both parent and child. How should I proceed?

my json data

[
{
    nome: "Carlos",
    comentario: "Esse dia foi show",
    resp: [ ]
},
{
    nome: "Andre",
    comentario: "Acho que não precisava disso",
    resp: [
    {
        nome: "inutil",
        comentario: "Sempre assim"
    },
    {
        nome: "Roberto",
        comentario: "Se não estivessem fazendo nada errado, não iam querer apagar a mídia."
    },
    {
        nome: "xumbinho",
        comentario: "André ! Para vai!"
    }
    ]
},
{
    nome: "Celso",
    comentario: "É pra acabar mesmo",
    resp: [ ]
}
]

And my ComentariosActivity code

private void makejsonobjreq() {
        PD.show();

        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET, url+"284901",
                null, response -> {
                    ArrayList<Group> list = new ArrayList<Group>();
                    ArrayList<Child> ch_list;

                    Log.d("response", String.valueOf(response));
                    try {
                        Iterator<String> key = response.keys();
                        while (key.hasNext()) {
                            String k = key.next();
                            Log.d("KEY", String.valueOf(k));

                            Group gru = new Group();
                            gru.setNome(k);
                            ch_list = new ArrayList<Child>();

                            JSONArray ja = response.getJSONArray(k);
                            Log.d("QNT", String.valueOf(ja.length()));

                            for (int i = 0; i < ja.length(); i++) {

                                JSONObject jo = ja.getJSONObject(i);

                                Child ch = new Child();
                                Log.d("COMENTARIO NOME",jo.getString("nome"));
                                ch.setNome(jo.getString("nome"));
                                ch.setComentario(jo.getString("comentario"));

                                ch_list.add(ch);
                            } // for loop end
                            gru.setItems(ch_list);
                            list.add(gru);
                        } // while loop end

                        ExpAdapter = new ExpandListAdapter(ComentariosActivity.this, list);
                        ExpandList.setAdapter(ExpAdapter);

                        PD.dismiss();

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                PD.dismiss();
                Log.d("response", String.valueOf(error));
            }
        });
        MyApplication.getInstance().addToRequestQueue(jsonObjReq, "jreq");
    }

Adapter

package br.inf.cgn.cgnapp;

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import com.android.volley.toolbox.ImageLoader;

import br.inf.cgn.cgnapp.model.Child;
import br.inf.cgn.cgnapp.model.Group;

public class ExpandListAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<Group> groups;

    ImageLoader imageLoader = MyApplication.getInstance().getImageLoader();

    public ExpandListAdapter(Context context, ArrayList<Group> groups) {
        this.context = context;
        this.groups = groups;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        ArrayList<Child> chList = groups.get(groupPosition).getItems();
        return chList.get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {

        Child child = (Child) getChild(groupPosition, childPosition);
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context
                    .getSystemService(context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.comentarios_resp, null);
        }

        if (imageLoader == null)
            imageLoader = MyApplication.getInstance().getImageLoader();

        TextView nome = (TextView) convertView.findViewById(R.id.nome_resp);
        nome.setText(child.getNome().toString());

        TextView comentario = (TextView) convertView.findViewById(R.id.comentario_resp);
        comentario.setText(child.getComentario().toString());

        return convertView;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        ArrayList<Child> chList = groups.get(groupPosition).getItems();
        return chList.size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groups.get(groupPosition);
    }

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

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        Group group = (Group) getGroup(groupPosition);
        if (convertView == null) {
            LayoutInflater inf = (LayoutInflater) context
                    .getSystemService(context.LAYOUT_INFLATER_SERVICE);
            convertView = inf.inflate(R.layout.comentarios_list, null);
        }
        TextView nome = (TextView) convertView.findViewById(R.id.nome);
        nome.setText(group.getNome());
        TextView comentario = (TextView) convertView.findViewById(R.id.comentario);
        comentario.setText(group.getComentario());

        return convertView;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

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

}

I tried several ways to make this code work but with no success!


Solution

  • I've added code that will parse the JSON response and populate the data for the adapter. It is a complete example. But it needs an XML file with an ExpandableListView named "list".

    I borrowed a basic adapter from another stackoverflow post. It only displays basic text, not the entire conversation. But it is probably enough code to get you unblocked. But you'll need to replace the simple views like: android.R.layout.simple_list_item_1 with your own views.

    In the real app, it is probably best to parse the JSON data in an ASyncTask.

    package com.example.elletlar.myapplication;
    import android.content.Context;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.ExpandableListView;
    import android.widget.TextView;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        List<Group> list = getList();
        ExpAdapter adapter = new ExpAdapter(this, list);
        ExpandableListView listView = findViewById(R.id.lst);
        listView.setAdapter(adapter);
    }
    
    public class Group {
        String name;
        private List<Child> childList;
    
        void setChildList(List<Child> list) {
            childList = list;
        }
        List<Child> getChildList() {
            return childList;
        }
    }
    
    public class Child {
        String name;
        String comment;
    }
    
    private ArrayList<Group> getList() {
        ArrayList<Group> list = new ArrayList<>();
        JSONArray groupArr;
        try {
            String TEST = "[" +
                    "{" +
                    "nome: \"Carlos\"," +
                    "                comentario: \"Esse dia foi show\"," +
                    "            resp: [ ]" +
                    "    }," +
                    "    {" +
                    "        nome: \"Andre\"," +
                    "                comentario: \"Acho que não precisava disso\"," +
                    "            resp: [" +
                    "        {" +
                    "            nome: \"inutil\"," +
                    "                    comentario: \"Sempre assim\"" +
                    "        }," +
                    "        {" +
                    "            nome: \"Roberto\"," +
                    "                    comentario: \"Se não estivessem fazendo nada errado, não iam querer apagar a mídia.\"\n" +
                    "        }," +
                    "        {" +
                    "            nome: \"xumbinho\"," +
                    "                    comentario: \"André ! Para vai!\"" +
                    "        }" +
                    "    ]" +
                    "    }" +
                    "]";
    
            groupArr = new JSONArray(TEST);
            ArrayList<Child> childList;
    
            for (int i = 0; i < groupArr.length(); ++i) {
                JSONObject groupObj= groupArr.getJSONObject(i);
                Group group = new Group();
                group.name = groupObj.getString("nome");
    
                childList = new ArrayList<>();
                JSONArray replyArr = groupObj.getJSONArray("resp");
                for (int j = 0; j < replyArr.length(); ++j) {
                    JSONObject childObj = replyArr.getJSONObject(j);
                    Child child = new Child();
                    child.name = (childObj.getString("nome"));
                    child.comment = (childObj.getString("comentario"));
                    childList.add(child);
                } // for loop end
    
                group.setChildList(childList);
                list.add(group);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    
        return list;
    }
    
    public class ExpAdapter extends BaseExpandableListAdapter {
    
        private final class ViewHolder {
            TextView textLabel;
        }
    
        private final List<Group> itemList;
        private final LayoutInflater inflater;
    
        private ExpAdapter(Context context, List<Group> itemList) {
            this.inflater = LayoutInflater.from(context);
            this.itemList = itemList;
        }
    
        @Override
        public Child getChild(int groupPosition, int childPosition) {
    
            return itemList.get(groupPosition).getChildList().get(childPosition);
        }
    
        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }
    
        @Override
        public int getChildrenCount(int groupPosition) {
            return itemList.get(groupPosition).getChildList().size();
        }
    
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
                                 final ViewGroup parent) {
            View resultView = convertView;
            ViewHolder holder;
    
            if (resultView == null) {
                resultView = inflater.inflate(android.R.layout.simple_list_item_1, null); //TODO change layout id
                holder = new ViewHolder();
                holder.textLabel = resultView.findViewById(android.R.id.text1); //TODO change view id
                resultView.setTag(holder);
            } else {
                holder = (ViewHolder) resultView.getTag();
            }
    
            final Child item = getChild(groupPosition, childPosition);
    
            holder.textLabel.setText(item.name);
    
            return resultView;
        }
    
        @Override
        public Group getGroup(int groupPosition) {
            return itemList.get(groupPosition);
        }
    
        @Override
        public int getGroupCount() {
            return itemList.size();
        }
    
        @Override
        public long getGroupId(final int groupPosition) {
            return groupPosition;
        }
    
        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View theConvertView, ViewGroup parent) {
            View resultView = theConvertView;
            ViewHolder holder;
    
            if (resultView == null) {
                resultView = inflater.inflate(android.R.layout.simple_list_item_1, null);
                holder = new ViewHolder();
                holder.textLabel = resultView.findViewById(android.R.id.text1);
                resultView.setTag(holder);
            } else {
                holder = (ViewHolder) resultView.getTag();
            }
    
            final Group item = getGroup(groupPosition);
    
            holder.textLabel.setText(item.name);
    
            return resultView;
        }
    
        @Override
        public boolean hasStableIds() {
            return true;
        }
    
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }
    }
    }
    

    Here are some samples of making HTTP requests: Using URLConnection

    Also, you might look at using the Volley framework: Volley

    Simple and very popular framework for HTTP requests: OK HTTP

    For Kotlin, I use Fuel: Fuel

    Beware, most of the answers on Stackoverflow about downloading items use a class called: DefaultHttpClient that is from the Apache library. Google decided to remove the Apache libraries a couple of Android versions ago. It is still possible to use them by tweaking the Gradle file, but that's only for legacy apps. New apps should use classes like: URLConnection. Converting Apache to Current Android HTTP Classes