user3358306
user3358306

Reputation: 187

Putting a JSONArray into a list(Android)

I have a project that can take a JSONObject and put it into a edittext but I'm trying to figure out how to change it so that it takes a JSONArray and puts it into a listView.

Here is my current code:

public class Js extends Activity {


private String url1 = "http://api.openweathermap.org/data/2.5/weather?q=chicago";
//private String url1 = "http://bisonsoftware.us/hhs/messages.json";
private TextView temperature;//,country,temperature,humidity,pressure;
private HandleJSON obj;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_js);
    //location = (EditText)findViewById(R.id.editText1);
    //country = (TextView)findViewById(R.id.editText2);
    temperature = (TextView)findViewById(R.id.editText3);
    //humidity = (EditText)findViewById(R.id.editText4);
    //pressure = (EditText)findViewById(R.id.editText5);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items
    //to the action bar if it is present.
    getMenuInflater().inflate(R.menu.js, menu);
    return true;
}

public void open(View view){
    //String url = location.getText().toString();
    //String finalUrl = url1 + url;
    //country.setText(url1);
    obj = new HandleJSON(url1);
    obj.fetchJSON();

    while(obj.parsingComplete);
    //country.setText(obj.getCountry());
    temperature.setText(obj.getTemperature());
    //humidity.setText(obj.getHumidity());
    //pressure.setText(obj.getPressure());

}
}

public class HandleJSON {

//private String country = "temperature";
private String temperature = "clouds";
//private String humidity = "humidity";
//private String pressure = "pressure";
private String urlString = null;

public volatile boolean parsingComplete = true;
public HandleJSON(String url){
    this.urlString = url;
}
/*public String getCountry(){
    return country;
}*/
public String getTemperature(){
    return temperature;
}
/*public String getHumidity(){
    return humidity;
}
public String getPressure(){
    return pressure;
}*/

@SuppressLint("NewApi")
public void readAndParseJSON(String in) {
    try {
        JSONObject reader = new JSONObject(in);

        //JSONObject sys  = reader.getJSONObject("main");
        //country = sys.getString("temp");

        JSONObject main  = reader.getJSONObject("clouds");
        temperature = main.getString("all");


        //pressure = main.getString("pressure");
        //humidity = main.getString("humidity");

        parsingComplete = false;



    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
public void fetchJSON(){
    Thread thread = new Thread(new Runnable(){
        @Override
        public void run() {
            try {
                URL url = new URL(urlString);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(10000 /* milliseconds */);
                conn.setConnectTimeout(15000 /* milliseconds */);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                // Starts the query
                conn.connect();
                InputStream stream = conn.getInputStream();

                String data = convertStreamToString(stream);

                readAndParseJSON(data);
                stream.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    thread.start();
}
static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}
}

I have been trying to figure this out for a while but can't find a good way to implement through the way I'm parsing the data. Thanks in advance for any help that is given.

Here is the JSON:

"messages":["This is a demo message.  Enjoy!","Another demonstration message stored in JSON format.","JSON stands for JavaScript Object Notation (I think)"]

Upvotes: 1

Views: 220

Answers (2)

RogueBaneling
RogueBaneling

Reputation: 4471

First, consider changing your JSONArray into a String[]. Look at the following code block for an example:

String[] jsonMessages = jsonArrayToStringArray(yourJsonArray);

public String[] jsonArrayToStringArray(JSONArray arr){
    List<String> list = new ArrayList<String>();
    for(int i = 0; i < arr.length(); i++){
        list.add(arr.getJSONObject(i).getString("name"));
    }
    return list.toArray(new String[list.size()]);
}

Next, now that you have a String[], you can build an adapter for your ListView and populate your ListView with an array.

First, you must get the ListView that is contained in your layout. Then you can build a simple adapter, and lastly, you must set the ListView's adapter to the adapter. For example:

ListView myListView = (ListView) findViewById(R.id.my_list_view);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, jsonMessages);
myListView.setAdapter(adapter);

In this ArrayAdapter, you are using a pre-created layout (that is quite basic). To create a more advanced view for each element of the ListView, you will need to make a custom adapter.

Upvotes: 0

Kevin Coppock
Kevin Coppock

Reputation: 134684

What you're really asking is several questions. Break it down for yourself, and I think you'll have a much easier time.

  1. Create functionality that executes an internet service request and returns the response, handling error cases, etc.

  2. Create a "Weather" class that reflects the contents of the JSON (e.g. for yours, a class with temperature, pressure, humidity, etc.)

  3. Create functionality that checks the response for validity and constructs a Weather object from it.

  4. Create a collection of these Weather objects (List, Set, etc.) from the response

  5. Create a custom ListAdapter that takes an instance of your Weather object and translates it to the UI.

  6. ???

  7. Profit

Taken individually, you'll have a much easier time tackling this. A custom adapter is very simple to implement. So, say you have a simple Weather class like this:

public final class Weather {
    public final String temperature;
    public final String pressure;
    public final String humidity;

    public Weather(String temperature, String pressure, String humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
    }

    public static Weather valueOf(JSONObject json) throws JSONException {
        String temperature = json.getString("temp");
        String pressure = json.getString("pressure");
        String humidity = json.getString("humidity");
    }
}

Make a simple subclass of BaseAdapter which takes your Weather and adapts it to a custom layout that you've created:

public final class WeatherAdapter extends BaseAdapter {
    private final List<Weather> mWeatherList;
    private final LayoutInflater mInflater;

    public WeatherAdapter(Context ctx, Collection<Weather> weather) {
        mInflater = LayoutInflater.from(ctx);
        mWeatherList = new ArrayList<>();
        mWeatherList.addAll(weather);
    }

    @Override public int getCount() {
        // Return the size of the data set
        return mWeatherList.size();
    }

    @Override public Weather getItem(int position) {
        // Return the item in our data set at the given position
        return mWeatherList.get(position);
    }

    @Override public long getItemId(int position) {
        // Not useful in our case; just return position
        return position;
    }

    @Override public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            // There's no View to re-use, inflate a new one.
            // This assumes you've created a layout "weather_list_item.xml"
            // with textviews for pressure, temperature, and humidity
            convertView = mInflater.inflate(R.layout.weather_list_item, parent, false);

            // Cache the Views we get with findViewById() for efficiency
            convertView.setTag(new WeatherViewHolder(convertView));
        }

        // Get the weather item for this list position
        Weather weather = getItem(position);
        WeatherViewHolder holder = (WeatherViewHolder) convertView.getTag();

        // Assign text, icons, etc. to your layout
        holder.pressure.setText(weather.pressure);
        holder.temperature.setText(weather.temperature);
        holder.humidity.setText(weather.humidity);

        return convertView;
    }

    public static class WeatherViewHolder {
        public final TextView pressure;
        public final TextView humidity;
        public final TextView temperature;

        public WeatherViewHolder(View v) {
            pressure = (TextView) v.findViewById(R.id.pressure);
            humidity = (TextView) v.findViewById(R.id.humidity);
            temperature = (TextView) v.findViewById(R.id.temperature);
        }
    }
}

Upvotes: 1

Related Questions