简体   繁体   中英

JSON Data in ListView using Custom Adapter

I am trying to create a custom Adapter from JSON Data, I can create a ListView with all the data packed in one row per record but I want each value to be in it's on row. Sample JSON

{
"outages": [
    {
            "outagnumber": "567273",
            "impact": "half a block",
            "status": "almost complete",
            "timestamp": "07-19-2015 12:00:00am"               
    },
    {
            "outagnumber": "567243",
            "impact": "whole block",
            "status": "whating on crew",
            "timestamp": "07-19-2015 11:00:00am"
    },


           ]
}

What is the best way of achieving this?

Adapter

public class CustomListOutageAdapter extends ArrayAdapter{

private final Activity context;
private final LinkedList<HashMap<String, String>> itemname;


public CustomListOutageAdapter(Activity context, LinkedList<HashMap<String, String>> itemname) {
    super(context, R.layout.mylistoutagedetails, itemname);
    // TODO Auto-generated constructor stub

    this.context = context;
}

public View getView(int position, View view, ViewGroup parent) {
    LayoutInflater inflater = context.getLayoutInflater();
    View rowView = inflater.inflate(R.layout.mylistoutagedetails, null, true);

    TextView txtTitle = (TextView) rowView.findViewById(R.id.name);


    txtTitle.setText(itemname.get(position).toString());
    return rowView;

};
}

I get a feeling you need some help understanding adapters, so let's start from scratch. Hopefully this helps you.

The issue you have is that a adapter is a just a single "cell", and the adapter will create x number of cells.

An adapter requires a list (arraylist, list, linkedlist...) and uses each element in the list as the content for the cell, and by default, the number of cells it will generate. You can override the getCount() method to dictate a different number of cells you may want. (you can even do something like someList.size() + 4 , or whatever else you want to add to the number of cells)

So, if you want to display those 8 elements in their own cells, you have a few options:

  • In the activity (not the adapter) you can create a new List (arrayList would probably be easier) with each element of the json. This make it so you pass 1 list with all the objects already separated individually. This is usually a bad practice and a bad idea, but since you want to display it in this odd way anyways, this might be quickest way.

  • Again in the activity you can create an object called "outages" which contains the elements in the "outages" tag (outagnumber, impact...), then you add those objects to a new list, and pass this new list to the adapter. The adapter will then have a list with 2 objects (in this example) and then you can create 2 cells with 4 textview elements each, and add each element of each object to each textview. This is probably the best way to do it, but each element won't be in its own cell.

  • You can go with the viewHolder approach suggested by @nolleh, although it will over complicate this issue since you're now using Recycler views.

Let me know if this helps.

Edit: Added example

Here's an example of how you can do it with an adapter for 2 cells, each cell including the text you want:

Activity class

public class OutagesActivity extends ListActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Please don't create objects like this. This is just an example
        Outages outagesObject = new Outages();
        outagesObject.outagnumber = jsonValue;
        outagesObject.impact = jsonValue;
        outagesObject.status = jsonValue;
        outagesObject.timestamp = jsonValue;

        List<Outages> listOfOutagesObjects = new ArrayList<Outages>();
        listOfOutagesObjects.add(outagesObject);
        listOfOutagesObjects.add(outagesObject2);

        OutagesAdapter adapter = new OutagesAdapter(listOfOutagesObjects);
        setListAdapter(adapter);
    }
}

Adapter class

public class OutagesAdapter extends ArrayAdapter<Outages>
{
    private List<Outages> listOfOutagesObjects;

    public InitialGetDataActivityAdapter(List<Outages> listOfOutagesObjects)
    {
        super(context, R.layout.single_row, listOfOutagesObjects);
        this.listOfOutagesObjects = listOfOutagesObjects;
    }

    @Override
    public int getCount() {
        return listOfOutagesObjects.size();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        Outages outagesObject = listOfParseObjects.get(position);
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rowView = inflater.inflate(R.layout.single_row, parent, false);

        TextView tv_outagnumber = (TextView) rowView.findViewById(R.id.tv_outagnumber);
        TextView tv_impact = (TextView) rowView.findViewById(R.id.tv_impact);
        TextView tv_status = (TextView) rowView.findViewById(R.id.tv_status);
        TextView tv_timestamp = (TextView) rowView.findViewById(R.id.tv_timestamp);

        tv_outagnumber.setText(outagesObject.outagnumber);
        tv_impact.setText(outagesObject.impact);
        tv_status.setText(outagesObject.status);
        tv_timestamp.setText(outagesObject.timestamp);

        return rowView;
    }
}

And you need to make your layout file (R.layout.single_row) with each textview you want in whatever layout order you want.

how about change items as JSONArray ? and I am not familier with your ArrayAdapter, changed as BaseAdapter.

the code would be like below .. there are some idiom like viewHolder, it is just keeps its' views, for convenient access.

import org.json.JSONArray;
public class CustomListOutageAdapter extends BaseAdapter{

private final Activity mContext;
private final JSONArray mData;
/// items is 
public CustomListOutageAdapter(Activity context, JSONArray items) {
    //super(context, R.layout.mylistoutagedetails, itemname);
    this.mContext = context;
    this.mData = items; 
}

public View getView(int position, View view, ViewGroup parent) {
    ViewHolder vh;
    if (view == null) {
        LayoutInflater inflater = context.getLayoutInflater();
        view = inflater.inflate(R.layout.mylistoutagedetails, null, true);
        vh = new ViewHolder();
        vh.txtName = (TextView) view.findViewById(R.id.name);
        view.setTag(vh);
    }
    else {
        vh = (ViewHolder) view.getTag();
    } 

    if (mData.size() > position) { 
        vh.txtTitle.setText(mData.get(position).toString());
    }
    return view;
}

public class ViewHolder {
     TextView txtName; // so on...   
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM