-4

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,

Dileep Patel
  • 1,988
  • 2
  • 12
  • 26
Gremio
  • 1
  • 2
  • what is error you are facing? – Sunil P Aug 16 '17 at 08:05
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: [How to create a Minimal, Complete, and Verifiable example.](https://stackoverflow.com/help/mcve) – LazerBanana Aug 16 '17 at 08:16
  • The jsonarray is empty so it fails at the for loop – Gremio Aug 16 '17 at 08:17

4 Answers4

1

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.

SniperDW
  • 293
  • 1
  • 6
0

You are returning ques as soon as you fire the background task. The background task will take some time to finish and till then your ques list will remain null so you will not see data.

Update the list in the postExecute method of AsyncTask.

Kapil G
  • 4,081
  • 2
  • 20
  • 32
0

try this

        quest = new ArrayList<Question>();
        for (int i = 0; i < jsonArray.length(); i++) {

            JSONObject jsonObject = jsonArray.getJSONObject(i);

            Question ques = new Question(); //inti Question
            //Enter Values to Question Object
            ques.setQuestion( jsonObject.getString("question"));
            ques.setAnswer1( jsonObject.getString("answer1"));
            ques.setAnswer2( jsonObject.getString("answer2"));
            ques.setAnswer3( jsonObject.getString("answer3"));
            ques.setAnswer4( jsonObject.getString("answer4"));
            ques.setCorrectAnswer( jsonObject.getString("correctanswer"));
            // Add Question Object to ArrayList
            quest.add(ques);
        }
Shailesh Bandil
  • 497
  • 7
  • 20
0

It is empty because you are returning null from the doInBackground(). The ideal way is to pass the result to onPostExecute() and set the adapter there.Like this :-

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

    @Override
    protected ArrayList<Question> 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 quest;
    }

    @Override
    protected void onPostExecute(ArrayList<Question> questions) {
        super.onPostExecute(questions);

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

        listv.setAdapter(arrayAdapter);
    }
}