Gremio Gremio - 2 years ago 96
Java Question

Fetch JSON Array to ArrayList to ListView

I have a php page (urldisplay) returning this array of question objects:

[{
"suggestid": "1",
"question": "What does Aotearoa mean?",
"answer1": "Maui and the Whale",
"answer2": "2 Islands",
"answer3": "Land of the Long White Cloud",
"answer4": "Isle of Greenstone",
"correctanswer": "Land of the Long White Cloud",
"userID": "1"
}, {
"suggestid": "2",
"question": "What does Haere Ra mean?",
"answer1": "Hello",
"answer2": "Goodbye",
"answer3": "Thanks",
"answer4": "Sorry",
"correctanswer": "Goodbye",
"userID": "1"
}, {
"suggestid": "3",
"question": "Where is Zealand?",
"answer1": "France",
"answer2": "Germany",
"answer3": "Denamrk",
"answer4": "Finland",
"correctanswer": "Denmark",
"userID": "1"
}, {
"suggestid": "4",
"question": "What does Aotearoa mean?",
"answer1": "Maui and the Whale",
"answer2": "2 Islands",
"answer3": "Land of the Long White Cloud",
"answer4": "Isle of Greenstone",
"correctanswer": "Land of the Long White Cloud",
"userID": "2"
}, {
"suggestid": "5",
"question": "What does Aotearoa mean?",
"answer1": "Maui and the Whale",
"answer2": "2 Islands",
"answer3": "Land of the Long White Cloud",
"answer4": "Isle of Greenstone",
"correctanswer": "Land of the Long White Cloud",
"userID": "3"
}]


I am trying to read the objects via this class (in my DAO class) which saves the results to an array list of questions

ArrayList<Question> quest;

public ArrayList<Question> ListSugg()
{
ListSuggestions sugg = (ListSuggestions)new ListSuggestions().execute();
return quest;
}

public class ListSuggestions extends AsyncTask<Void, Void, Void> {

@Override
protected Void doInBackground(Void... params) {

try {
URL url = new URL(urldisplay);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
JSONArray jsonArray = new JSONArray(con);
quest = new ArrayList<Question>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String question = jsonObject.getString("question");
String answer1 = jsonObject.getString("answer1");
String answer2 = jsonObject.getString("answer2");
String answer3 = jsonObject.getString("answer3");
String answer4 = jsonObject.getString("answer4");
String correctanswer = jsonObject.getString("correctanswer");
Question ques = new Question(0, question, answer1, answer2, answer3, answer4, correctanswer);
quest.add(ques);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e1) {
e1.printStackTrace();
}
return null;
}
}


quest stays empty though. I then want to add the question objects to a ListView.

public class ListActivity extends AppCompatActivity {
ListView listv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
listv = (ListView)findViewById(R.id.ListDisplay);
DAO dao = new DAO();
ArrayList list = dao.ListSugg();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
list );

listv.setAdapter(arrayAdapter);
}


I've tried a bunch of other SO posts but I seem to be chasing my tail. Can anyone spot my mistakes/is there a better way for me to do this?

Cheers,

Answer Source

The issue is that AsyncTask executes code Asunchrounsly, meaning that when you call ListSugg(), it will run the background task on another thread and return you the quest object before the background quest is finished, meaning you'll have a still empty list. read here for more info

What you can do, is that you override the onPostExecute method, and set the adapter there, like so:

public class ListSuggestions extends AsyncTask<Void, Void, Void> {

    @Override
    protected Boolean doInBackground(String... params) {
        // do something
        return true;
    }

    @Override
    protected void onPostExecute(String result) {
        // The results of the above method
        // Processing the results here

        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
             this,
             android.R.layout.simple_list_item_1,
             list);

        listv.setAdapter(arrayAdapter);

    }

}

But for this to work, you need to include your AsyncTask inside the MainActivity.

This should solve your issue, hope it helps.

However, there are much better and simpler solutions like using an HTTP networking library like okhttp or Retrofit, and using a JSON parser like Gson, you can check them out if you'd like.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download