0
I’m trying to get values from a json
and play in a recycleview
using OkHttp
, he is taking the values and playing in the list, no errors, but I am not able to pass these values to the Adapter, the list is reaching null on fragment
, I’m pretty sure the problem is with thread
, probably the main thread is taking the value of the list before the callback
set...
How to solve?
Class where I take the json values: (I think the problem is in the method sendGetRecipes
)
public class HttpRequest {
private List<Recipes> recipesList;
public void sendGetRecipes(String url) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String strResponse = response.body().string();
setRecipesList(strResponse);
Log.d("HTTP", "PASSOU!!!!!");
Log.d("HTTP", strResponse);
}
});
}
public void setRecipesList(String response) {
recipesList = new ArrayList<>();
List<Ingredients> ingredientsList = new ArrayList<>();
List<Steps> stepsList = new ArrayList<>();
if (response != null) {
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Recipes recipes = new Recipes();
recipes.setId(jsonObject.getInt("id"));
recipes.setName(jsonObject.getString("name"));
recipes.setImage(jsonObject.getString("image"));
recipes.setServings(jsonObject.getInt("servings"));
JSONArray ingrJsonArray = jsonObject.getJSONArray("ingredients");
for (int j = 0; j < ingrJsonArray.length(); j++) {
JSONObject ingrJsonObject = ingrJsonArray.getJSONObject(j);
Ingredients ingredients = new Ingredients();
ingredients.setIngredient(ingrJsonObject.getString("ingredient"));
ingredients.setMeasure(ingrJsonObject.getString("measure"));
ingredients.setQuantity(ingrJsonObject.getInt("quantity"));
ingredientsList.add(ingredients);
//Log.d("ARRAY-JSON-INGR", ingrJsonObject.getString("ingredient"));
}
JSONArray stepsJsonArray = jsonObject.getJSONArray("steps");
for (int j = 0; j < stepsJsonArray.length(); j++) {
JSONObject stepsJsonObject = stepsJsonArray.getJSONObject(j);
Steps steps = new Steps();
steps.setId(stepsJsonObject.getInt("id"));
steps.setDescription(stepsJsonObject.getString("description"));
steps.setShortDescription(stepsJsonObject.getString("shortDescription"));
steps.setVideoUrl(stepsJsonObject.getString("videoUrl"));
steps.setThumbnailUrl(stepsJsonObject.getString("thumbnailUrl"));
stepsList.add(steps);
//Log.d("ARRAY-JSON-INGR", ingrJsonObject.getString("ingredient"));
}
recipes.setIngredientsList(ingredientsList);
recipes.setStepsList(stepsList);
recipesList.add(recipes);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public List<Recipes> getRecipesList() {
return recipesList;
}
}
Fragment (commented on where he tries to get the list)
public class MainFragment extends Fragment {
private static final String TAG = MainFragment.class.getSimpleName();
private RecyclerView recipesRecycleView;
private List<Recipes> recipesList;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
recipesRecycleView = (RecyclerView) view.findViewById(R.id.recipesRecycleView);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recipesRecycleView.setLayoutManager(layoutManager);
HttpRequest httpRequest = new HttpRequest();
httpRequest.setRecipesList(Recipes.RECIPES_URL);
recipesList = httpRequest.getRecipesList(); // <------------- AQUI
RecipesAdapter recipesAdapter = new RecipesAdapter(getActivity(), recipesList);
recipesRecycleView.setAdapter(recipesAdapter);
return view;
}
}
I didn’t post the Adapter code because the problem isn’t there
It didn’t work, but maybe it’s because I don’t understand what you mean... I don’t understand why you’re calling getRecipes inside setRecipesList
– felipe.rce
getRecipes() is the callback of the interface I created. I placed inside the setRecipesList, at the end of the method, to pass the list of recipes generated nomesmo to Handler that is implementing the interface, in this case your Fragment. The idea is that your Fragment awaits the completion of sendGetRecipes and only update the list Adapter when the list is ready, the problem, by better analyzing the code now, is that it is not being called anywhere in the code. I confused the name of this method with setRecipesList. I’ll take a closer look at the code later and edit my answer.
– Márcio Oliveira
This error "android.view.Viewrootimpl$Calledfromwrongthreadexception: Only the original thread that created a view Hierarchy can touch its views."
– felipe.rce
Yes, as I confused the name of the methods and answered in a hurry, it won’t even work. Later I see calmly, because I am at work.
– Márcio Oliveira
I actually noticed this and changed the name of the method to getRecipesList, now I solved this problem by setting this Adapter in Uithread (runOnUiThread), I still didn’t understand 100% of what you did, my java is really weak, I didn’t know I could use interface like this, and tb a little confused with threads on Android, but I’m giving a read here... Updates your answer with the name of the true method I accept it here
– felipe.rce
Dude, I edited my answer, but basically all that was missing was correcting the httprequest call by changing the name of the method. All the rest of the suggestions I’ve made I believe are correct.
– Márcio Oliveira