2

I have a problem on how to display my json data to a recycler view. Here is my JSON data in which I want to display both the "match" and "replacement" object values in a single recycler view. I already work with some other json structure but this one is kind of complicated to me so I don't know how will I do it.

{
  "software": {
     "name": "GrammarBot",
     "version": "4.3-SNAPSHOT",
     "apiVersion": 1,
     "premium": false,
     "premiumHint": "You might be missing errors only the Premium version can find. Upgrade to see what you're missing.",
     "status": ""
      },
  "warnings": {
     "incompleteResults": false
     },
  "language": {
     "name": "English",
     "code": "en-US",
     "detectedLanguage": {
        "name": "English (US)",
        "code": "en-US"
        }
    },
  "matches": [
   {
     "message": "Statistics suggests that 'there' (as in 'Is there an answer?') might be the correct word here, not 'their' (as in 'It’s not their fault.'). Please check.",
     "shortMessage": "",
     "replacements": [
        {
        "value": "there"
        }
      ],
    "offset": 27,
    "length": 5,
    "context": {
       "text": "I can't remember how to go their.",
       "offset": 27,
       "length": 5
       },
    "sentence": "I can't remember how to go their.",
    "type": {
       "typeName": "Other"
        },
    "rule": {
       "id": "CONFUSION_RULE",
       "description": "Statistically detect wrong use of words that are easily confused",
       "issueType": "non-conformance",
       "category": {
           "id": "TYPOS",
            "name": "Possible Typo"
            }
        }
     }
   ]
}

My desired RecyclerView will looks like:

Match 1, Replacement 1, Match 2, Match 3, Replacement 2

Here are my codes:

Service (Interface)

public interface Service {

      @GET("/v2/check?")
      Call<GrammarBotMain> readErrorsGrammar(@Query("api_key") String api_key,
                                       @Query("text") String text,
                                       @Query("language") String language);
 }

Model class:

GrammarBotMain.java

public class GrammarBotMain {

    @SerializedName("software")
    private Software software;

    @SerializedName("warnings")
    private Warning warning;

    @SerializedName("language")
    private Language language;

    @SerializedName("matches")
    private ArrayList<Match> matches;

    //--getter and setter
}

Match.java

public class Match {

    @SerializedName("message")
    private String message;

    @SerializedName("shortMessage")
    private String shortMessage;

    @SerializedName("replacements")
    private ArrayList<Replacement> replacements;

    @SerializedName("offset")
    private int offset;

    @SerializedName("length")
    private int length;

    @SerializedName("context")
    private Context context;

    @SerializedName("sentence")
    private String sentence;

    @SerializedName("type")
    private Type type;

    @SerializedName("rule")
    private Rule rule;

    //--getter and setter
 }

Replacement.java

public class Replacement {

    @SerializedName("value")
    private String value;

    //--getter and setter
 }

Adapter

public class ResultAdapter extends RecyclerView.Adapter<ResultAdapter.ResultViewHolder>{

Context mContext;
ArrayList<Match> matchList = new ArrayList<>();
ArrayList<Replacement> replacementList = new ArrayList<>();

public ResultAdapter (Context mContext, ArrayList<Match> matchList){
    this.matchList = matchList;
    this.mContext = mContext;
}


@Override
public ResultViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.result_card, viewGroup, false);
    return new ResultViewHolder(view);
}

@Override
public void onBindViewHolder(ResultViewHolder resultViewHolder, int i) {

    Match match = matchList.get(i);
    resultViewHolder.mBadErrorTextView.setText(match.getSentence());
    resultViewHolder.mBetterErrorTextView.setText(match.getMessage());
}
 //viewholder and getcount
}

Fragment class

public class Tab1Fragment_GrammarChecker extends Fragment {

@BindView(R.id.InputTextEditText)
EditText mInputGrammarEditText;

@BindView(R.id.ErrorsRecyclerView)
RecyclerView mErrorsRecyclerView;

public static String userInput;
public String apiKey = "";
public String language = "en-US";

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.tab1_grammar_checker, container, false);

    ButterKnife.bind(this, view);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
    mErrorsRecyclerView.setLayoutManager(layoutManager);
    mErrorsRecyclerView.setItemAnimator(new DefaultItemAnimator());

    return view;
}

//onClick

public void loadJson(){
    Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl("http://api.grammarbot.io")
            .addConverterFactory(GsonConverterFactory.create());

    Retrofit retrofit = builder.build();
    Service serviceAPI = retrofit.create(Service.class);
    Call<GrammarBotMain> loadErrorsCall = serviceAPI.readErrorsGrammar(apiKey, userInput, language);

    final ProgressDialog progressDialog;
    progressDialog = new ProgressDialog(getActivity());
    progressDialog.setMax(100);
    progressDialog.setMessage(getResources().getString(R.string.progressDialogLoadingResultMessage));
    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressDialog.show();

    loadErrorsCall.enqueue(new Callback<GrammarBotMain>() {
        @Override
        public void onResponse(Call<GrammarBotMain> call, Response<GrammarBotMain> response) {
            progressDialog.dismiss();
            GrammarBotMain grammarBotMain = response.body();

                ArrayList<Match> matches = grammarBotMain.getMatches();

                mErrorsRecyclerView.setAdapter(new ResultAdapter(getContext(), matches));
                Log.i("Fragment", "SUCCESS");
            }

        @Override
        public void onFailure(Call<GrammarBotMain> call, Throwable t) {
            progressDialog.dismiss();
            Log.e("Error: ", t.getMessage());
        }
    });
}

}
16
  • Thanks for providing detailed information, but your requirement is not clear. Your JSON structure seems to have array of match objects with array of replacement objects for every match object. Can you clarify a bit? Commented Jan 5, 2019 at 20:46
  • @sourav.bh Hi! You are right, the match is an array of objects in which part of that object is an array of replacement. Sorry if it is kinda confusing since It is already a structured JSON because it is from an API that I am using right now. Commented Jan 5, 2019 at 20:50
  • That's not the confusion for me. I couldn't understand your requirement, like what is stopping you to create a RecyclerView with this JSON structure. Please state your problem more specifically. Commented Jan 5, 2019 at 20:54
  • @sourav.bh sorry. what i mean is that I want to display some objects of the match and the object of replacement at the same time in the same recyclerview but I don't know how will I do it or call it. Commented Jan 5, 2019 at 20:57
  • okay, suppose we have a RecyclerView example where the rows are represented in a comma seperated string. which one you want: match1+replacement1, match1+replacement2, match2+replacement2, ... or match1, replacement1, match2, match3, replacement2, ...? Commented Jan 5, 2019 at 21:06

1 Answer 1

2

I don't know how you decide to maintain the list order. But if you want to mix both types of objects value in the same RecyclerView then you can follow these steps:

1) Use an ArrayList of Object instead of Match or Replacement ArrayLists into your adapter. Add your Match and Replacement objects into that objects list according to your desired order.

ArrayList<Object> data = new ArrayList<>();
data.add(match1);
data.add(replacement1);
data.add(match2);

2) Decide the type of view you are currently required to handle in either onCreateViewHolder() and onBindViewHolder() by this kind of method:

int VIEW_TYPE_MATCH = 1;
int VIEW_TYPE_REPLQCEMENT = 2;

private int getViewType(int position) {
   Object value = data.get(position);
   if (value instanceof Match) return VIEW_TYPE_MATCH;
   else return VIEW_TYPE_REPLQCEMENT;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.