简体   繁体   中英

How to get a JSONArray to populate into a ListActivity's ListView

This is a post to an answer that I could not really find a good solution to. I searched quite a bit and I couldn't find anything decent. I don't know if the method I'm using is the best way, but it works and i feel that it is a fairly clean solution.

Were going to make a few assumptions here.

  1. that you know what a JSONArray is and have already somehow populated the JSONArray with some data.
{"result":
    [
      {"ACTIVE":"1","ID":"1","MAX_POPULATION":"1000","NAME":"Server 1","URL":"http://local.orbitaldomination.com/"},
      {"ACTIVE":"1","ID":"2","MAX_POPULATION":"1000","NAME":"Server 2","URL":"http://server2.orbitaldomination.com/"}
    ]
}

This is my JSON code that is populated into my JSONArray.

  1. You have already created a ListActivity with a ListView element inside it, and that you have created a layout. If you need more information on how to do that you can reference to Creating Lists Using the ListActivity

Okay, so here is where the real magic is..

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Pretty much ignore this .. it won't have anything to do with the example.
    // Your setContentView should be your layout with your list element.
    setContentView(R.layout.server_selection);

    //psuedo code 
    //JArrayServers = JSONArray that has my data in it.

    //Create a blank ( for lack of better term ) ArrayAdapter
    ArrayAdapter<String> servers = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);

    //Loop though my JSONArray
    for(Integer i=0; i< jArrayServers.length(); i++){
        try{
            //Get My JSONObject and grab the String Value that I want.
            String obj = jArrayServers.getJSONObject(i).getString("NAME");

            //Add the string to the list
            servers.add(obj);
        }catch(JSONException e){

        }
    }
    //Add my Adapter via the setListAdapter function.
    setListAdapter(servers);

    //Display the listView
    ListView lv = getListView();
    lv.setTextFilterEnabled(true);
}

I am creating a blank ArrayAdapter from what I can tell. I then loop though the array getting my string and inserting it into the adapter as I move along. Finally, at the end of the loop, I am inserting the adapter via the setListAdapter() function.

Pretty simple I think, but took a lot of research to come up with this, from a rookie. I'm sure all you experts out there will have a better way. If you do, post it somewhere easy to find please!

The best way to achieve this is in fact to roll your own custom adapter that extends BaseAdapter. I struggled with this issue for a day trying to avoid doing a pointless iteration of a JSONArray just to fill an array and use it in a "normal" ArrayAdapter. My situation was very similar to yours, with the small diference that i wanted to populate a spinner and not a ListView. Despite that, i will post the solution i found, because it may be helpful to you or someone else.

In your activity class:

public void initSpinner(JSONArray jsonArray)
{
     Spinner spinner = new Spinner(this);
     JSONArrayAdapter jsonArrayAdapter = new JSONArrayAdapter(this, countries, "Name");
     spinner.setAdapter(jsonArrayAdapter);
}

NOTE: the string "name" i pass has a parameter to my adapter is simply the key i wish to look for in my json data, in your case, it might be whatever key you are looking for.

Next, you need to roll your own spinner list item, wrapped in a RelativeLayout. I did this in a file called spinner_item.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dip" >

<TextView
    android:id="@+id/spinnerListItemName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:textColor="#000000"
    android:textSize="16dip" />

<RadioButton
    android:id="@+id/spinnerRadioButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_alignParentRight="true"
    android:paddingRight="6dip"
    android:focusable="false"
    android:clickable="false" />

<TextView
    android:id="@+id/spinnerListItemID"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="invisible" />

</RelativeLayout>

NOTE: the text view with id spinnerListItemID i just use because i want to store the id of the last button that i chose to simulate the behavior of a RadioButtonGroup, its very likely that there is a better way to acomplish this task, this is just the way that i found suited better at the time.

Finally, and most importantly, you need to create your JsonArrayAdapter class:

public class JSONArrayAdapter extends BaseAdapter implements OnTouchListener
{

private ViewGroup group;
private JSONArray items;
private String key;
private Context context;
private String selectedItemID;
private int selectedItemPosition;

public JSONArrayAdapter(Context ctx, JSONArray array, String k)
{
    super();
    this.items = array;
    this.context = ctx;
    this.key = k;
    this.selectedItemPosition = -1;
}

public int getCount()
{
    return items.length();
}

public Object getItem(int position)
{
    return position;
}

public long getItemId(int position)
{
    return position;
}

public View getView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    group = parent;

    if (view == null)
    {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = vi.inflate(R.layout.spinner_item, null);
        view.setOnTouchListener(this);
    }

    String itemText = null;
    String itemID = null;

    try
    {
        JSONObject jsonObject = items.getJSONObject(position);
        itemText = jsonObject.getString(key);
        itemID = jsonObject.getString("ID");
    }
    catch (JSONException e)
    {

    }

    if (itemText != null)
    {
        TextView name = (TextView) view.findViewById(R.id.spinnerListItemName);
        TextView id = (TextView) view.findViewById(R.id.spinnerListItemID);
        RadioButton button = (RadioButton) view.findViewById(R.id.spinnerRadioButton);

        if (name != null)
            name.setText(itemText);

        if (id != null)
        {
            id.setText(itemID);
            id.setHint(position + "");
        }

        if (id.getText().toString().equals(selectedItemID))
        {
            button.setSelected(true);
            button.setChecked(true);
        }
        else
        {
            button.setSelected(false);
            button.setChecked(false);
        }
    }

    if (selectedItemPosition == -1 && position == 0)
        this.setFirstChosen(view);

    return view;
}

private void setFirstChosen(View view)
{
    RadioButton button = (RadioButton) view.findViewById(R.id.spinnerRadioButton);
    button.setSelected(true);
    button.setChecked(true);

    selectedItemID = ((TextView) view.findViewById(R.id.spinnerListItemID)).getText().toString();
    selectedItemPosition = Integer.parseInt(((TextView) view.findViewById(R.id.spinnerListItemID)).getHint().toString());
}

public boolean onTouch(View v, MotionEvent event)
{
    RadioButton button = (RadioButton) v.findViewById(R.id.spinnerRadioButton);

    if (selectedItemPosition != -1)
    {
        View previousView = group.getChildAt(selectedItemPosition);
        if (previousView != null)
        {
            RadioButton previous = (RadioButton) previousView.findViewById(R.id.spinnerRadioButton);
            previous.setSelected(false);
            previous.setChecked(false);
        }
    }

    button.setSelected(true);
    button.setChecked(true);
    selectedItemID = ((TextView) v.findViewById(R.id.spinnerListItemID)).getText().toString();
    selectedItemPosition = Integer.parseInt(((TextView) v.findViewById(R.id.spinnerListItemID)).getHint().toString());

    return false;
}

}

There you have it, worked like a charm for me, and i know the pain it is to find information on this subject on-line :)

Another approach is to create your own adapter class, extending BaseAdapter . This would be useful if, for example, there were more than one piece of data you needed for each ListView row.

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