Display name
Display name

Reputation: 730

Looping out JSON Array using ArrayList

I am trying to learn retrofit and I have made successful attempts at posting data and now I am trying to retrieve JSON array which looks as follows:

{
  "result": "success",
  "message": "All Questions Have Been Selected",
  "question": {
      "all_question_ids": ["1","2","3"]
  }
}

I am using the following getter

public ArrayList getAll_question_ids(){
     return all_question_ids;
  }

I am retrieving using Retrofit as follows

if (resp.getResult().equals(Constants.SUCCESS)) {

                SharedPreferences.Editor editor = pref.edit();

                Log.d("Question_IDs", "getAllQuestionID() = " + response.body().getQuestion().getAll_question_ids() );

                editor.putString(Constants.All_QUESTION_IDS,((resp.getQuestion().getAll_question_ids().toString())));
                editor.apply();

            }
            progress.setVisibility(View.INVISIBLE);

It is here that I am stuck, as I am retrieving the array ok but I am unsure how to loop out the Array which is now stored in Shared Preferences.

When I place a toast to show me how the IDs are coming across, my toast confirms the data as [1,2,3]

The goal is to add a dynamic button and the individual ID, i.e button 1, button 2 etc every-time the loop is iterated.

I have tried the following:

String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");

 for (int i =0; i < questionNumber.length(); i++) {


            try {

        /*Dynamically create new Button which includes the question name
          */

                AppCompatButton btn_question = new AppCompatButton(getActivity());

        /*LayoutParams (int width, int height,float weight)
        As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
        the dynamically added EditText is the same size on all devices.
         */
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
                btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
                btn_question.setTextColor(Color.WHITE);
               // btn_question.setText(String.valueOf(x));
                btn_question.setText("Question "+ pref.getString(Constants.All_QUESTION_IDS,""));
                btn_question.setGravity(Gravity.CENTER);
                //generate unique ID for each new EditText dynamically created
                View.generateViewId();

                //Log.d("TEST VALUE", "Question1 generated ID = " + btn_question.generateViewId());


                params.setMargins(0, dpToPx(10), 0, dpToPx(10));
                btn_question.setPadding(0, 0, 0, 0);
                btn_question.setLayoutParams(params);
                allEds.add(btn_question);
                mLayout.addView(btn_question);


            } catch (Exception e) {
                Log.d(TAG, "Failed to create new edit text");
            }
        }

However the above is adding the value as it appears in the array e.g [1,2,3] which is obviously not what I want.

I have added a photo in case my explanation isn't clear. I want a button with 1 number added to it each time the loop iterates but I am unable to figure this out.

I have looked through lots of resource but cannot find an answer that is relevant to my problem, although, if there is, I am not familiar enough to recognise a similar issue.

If someone can offer some assistance, I would appreciate it!

enter image description here

Upvotes: 0

Views: 69

Answers (2)

copolii
copolii

Reputation: 14506

When you call editor.putString(Constants.All_QUESTION_IDS,((SOMETHING.toString())));, what is actually stored depends on the implementation of the toString method in the type of SOMETHING (in this case String[]). So avoid doing that. Instead, since you're already using Gson or Jackson (or others), store the question_idsas JSON:

final String jsonIds = gson.toJson (resp.getQuestion().getAll_question_ids());
editor.putString(Constants.All_QUESTION_IDS, jsonIds);

Your actual stored value no longer depends on the implementation of something that you don't control (String[].toString). It is a valid JSON array and regardless of what tool/library you use to read it back, it's valid.

Now, to read back the stored data:

final String storedJson = pref.getString(Constants.All_QUESTION_IDS, null);
if (null == storedJson) {
  // TODO: No question ids found
}

final String[] ids = gson.fromJson (storedJson, String[].class);
for (int i = 0; i < ids.length; i++) {
  // make your buttons
}

Upvotes: 1

Ben P.
Ben P.

Reputation: 54244

This is a problem of saving and then reading out a List of items (in this case, String instances).

You've chosen to save the list by calling editor.putString() with a value of getAll_question_ids().toString(). That toString() call is going to return a string representation of your list, or, in other words, a String instance with the value [1, 2, 3]. At this point, you no longer have a List proper, but a String that looks like a list.

This is all technically fine, but it means you have to take this into account when you're trying to read out that list.

You've written this to read the list back out:

String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");

Once this line executes, questionNumber will be a String instance with the value [1, 2, 3]. Again, this is fine, but now we come to the key point: we have to convert this String back into a List.

If you know for sure that the values in this list won't have commas in them, you can do it easily:

  • Trim the braces off the string using substring()
  • Create a String[] using split()
  • Convert your array to a list using Arrays.asList() (you could even skip this step since iterating over an array is just as easy as iterating over a list)

Put that together and you get:

String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
questionNumber = questionNumber.substring(1, questionNumber.length() - 1);
String[] array = questionNumber.split(", ");
List list = Arrays.asList(array);

At this point, you can iterate over your array or list:

for (String value : list) {
    ...
    btn_question.setText("Question " + value);
    ...
}

Upvotes: 1

Related Questions