'How do I add API data to a fragment's recycler view using query text listener to call the GET query
I created a requestManager class
package com.example.pantry;
import android.content.Context;
import com.example.pantry.models.apiResponse;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Query;
public class requestManager {
Context context;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.spoonacular.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
public requestManager(Context context){this.context = context;}
public void getFoodNames(OnFetchDataListener listener, String query){
callFoodApi CallFoods = retrofit.create(callFoodApi.class);
Call<apiResponse> call = CallFoods.callFoods(context.getString(R.string.api_key), query, "5");
call.enqueue(new Callback<apiResponse>() {
@Override
public void onResponse(Call<apiResponse> call, Response<apiResponse> response) {
if(!response.isSuccessful()){
listener.didNotFetch(response.message());
}
listener.didFetch(response.body(), response.message());
}
@Override
public void onFailure(Call<apiResponse> call, Throwable t) {
listener.didNotFetch(t.getMessage());
}
});
}
private interface callFoodApi{
@GET("food/ingredients/search")
Call<apiResponse> callFoods(
@Query("apiKey") String apiKey,
@Query("query") String query,
@Query("number") String number
);
}
}
and a FetchDataListener interface
package com.example.pantry;
public interface OnFetchDataListener<apiResponse> {
void didFetch(apiResponse response, String message);
void didNotFetch(String message);
}
and here is my fragment code
RecyclerView recyclerView;
addFoodAdapter adapter;
requestManager manager;
SearchView searchView;
String foodNames;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_add_food, container, false);
searchView = view.findViewById(R.id.addFoodSearch);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
foodNames = query;
manager.getFoodNames(listener, foodNames);
Log.d("executed", "submitted");
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return view;
}
private final OnFetchDataListener<apiResponse> listener = new OnFetchDataListener<apiResponse>() {
@Override
public void didFetch(apiResponse apiResponse, String message) {
recyclerView = recyclerView.findViewById(R.id.addFoodRecycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter = new addFoodAdapter(apiResponse.results);
recyclerView.setAdapter(adapter);
}
@Override
public void didNotFetch(String message) {
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
}
};
The adapter
package com.example.pantry;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.pantry.models.Result;
import java.util.List;
public class addFoodAdapter extends RecyclerView.Adapter<addFoodViewHolder> {
private List<Result> foodNames;
public addFoodAdapter(List<Result> foodNames){
this.foodNames = foodNames;
}
@NonNull
@Override
public addFoodViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new addFoodViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.add_food_row, parent, false));
}
@Override
public void onBindViewHolder(@NonNull addFoodViewHolder holder, int position) {
holder.foodName.setText(foodNames.get(position).getName());
}
@Override
public int getItemCount() {
return foodNames.size();
}
}
and the viewholder
package com.example.pantry;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class addFoodViewHolder extends RecyclerView.ViewHolder {
TextView foodName;
public addFoodViewHolder(@NonNull View itemView) {
super(itemView);
foodName = itemView.findViewById(R.id.addFoodItem);
}
}
but when I try and run it, and I submit the search query the app crashes and I get an error response in the log
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.pantry.requestManager.getFoodNames(com.example.pantry.OnFetchDataListener, java.lang.String)' on a null object reference
I've tried to solve it and figured out the crash and error only come when the search is submitted. I've only been doing this for a couple of months so still learning but I'm very lost, is it a fragments problem or am I just misunderstanding how fragments work? Any help would be greatly appreciated.
Solution 1:[1]
I didn't initalizee the manager
solved
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_add_food, container, false);
searchView = v.findViewById(R.id.addFoodSearch);
*manager = new requestManager(getContext());*
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
foodNames = query;
manager.getFoodNames(listener, foodNames);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return v;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Phil Morrison |
