Cannot Set Data to RecyclerView via Retrofit in Android - android

I can normally get and show data on Toast message, but I cannot add them to RecyclerView. How can I do this? Please help me. Thanks. I am sharing my code below.
NewsCatalog.java
public class NewsCatalog {
public List<MainNodes> nodes;
}
MainNodes.java
public class MainNodes {
public SubNodes node;
}
SubNodes.java
public class SubNodes {
public String body;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
NewsInterface
public interface NewsService {
String BASE_URL = "http://test.muhabirce.de/app/term/";
#GET("saglik")
Call<NewsCatalog> newsCatalog();
}
Adapter.java
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private ArrayList<SubNodes> subNodes;
private Context context;
public NewsAdapter(ArrayList<SubNodes> subNodes, Context context) {
this.subNodes = subNodes;
this.context = context;
}
#Override
public NewsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context)
.inflate(R.layout.card_view_items, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(NewsAdapter.ViewHolder holder, int position) {
holder.tvText.setText(subNodes.get(position).getBody());
}
#Override
public int getItemCount() {
return subNodes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView tvText;
public ViewHolder(View itemView) {
super(itemView);
tvText = (TextView) itemView.findViewById(R.id.tvText);
}
}
}
MainActivity.java
private void bindDatas() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(NewsService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
NewsService newsService = retrofit.create(NewsService.class);
Call<NewsCatalog> requestCatalog = newsService.newsCatalog();
requestCatalog.enqueue(new Callback<NewsCatalog>() {
#Override
public void onResponse(Call<NewsCatalog> call, Response<NewsCatalog> response) {
SubNodes subNodess = new SubNodes();
if (!response.isSuccessful()) {
Log.i("TAG", "Error: " + response.code());
} else {
NewsCatalog catalog = response.body();
try {
for (MainNodes m : catalog.nodes
) {
subNodess.setBody(m.node.body);
}
} catch (Exception e) {
Log.i(TAG, "" + e.getMessage());
}
}
subNodes.add(subNodess);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<NewsCatalog> call, Throwable t) {
Log.e(TAG, "Error: " + t.getMessage());
}
});
}
}

You should not create a new Subnodes object in response callback. Adapter does not have reference to this object and so the changes in data is not reflected. Update the subnodes object in the recyclerview adapter. Then only notifyDataSetChanged() will reflect the change in data.

Related

I'm stuck somewhere in between getting json array inside a object setting to recview, I have to send a key to fetch data in. Didn't get solutions here

I'm stuck somewhere in between getting json array inside a object setting it to recylerview, I have to send a key to fetch data and getting response in json array inside a object. Didn't understand solutions got here, so I'm here if Somebody can help mre understand.
////Main class
public class today_doctors extends AppCompatActivity {
viewModel_doc listViewModel;
List<model_doc> datalist;
todayDoctorAdapter adapter;
TextView clinic_name;
RecyclerView recview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_today_doctors);
recview=findViewById(R.id.rv);
recview.setLayoutManager(new LinearLayoutManager(this));
recview.addItemDecoration(new DividerItemDecoration(this, 0));
adapter=new todayDoctorAdapter(datalist);
recview.setAdapter(adapter);
clinic_name=findViewById(R.id.tvDrName);
process();
}
public void process(){
listViewModel= new ViewModelProvider(this).get(viewModel_doc.class);
listViewModel.getDatalistObserver ().observe(this, new Observer<List<model_doc>>() {
#Override
public void onChanged(List<model_doc> Models) {
if(Models!=null) {
datalist= Models;
adapter.updateList(Models);
}
else
{
recview.setVisibility(View.GONE);
Toast.makeText(today_doctors.this, "No data recieved", Toast.LENGTH_SHORT).show();
}
}
});
listViewModel.makeApiCall();
}
//////////Viewmodel class
public class viewModel_doc extends ViewModel
{
private MutableLiveData<List<model_doc>> datalist2;
public viewModel_doc(){
datalist2=new MutableLiveData<>();
}
public MutableLiveData<List<model_doc>> getDatalistObserver()
{
return datalist2;
}
public void makeApiCall()
{
apiSet apiServices= apiController.getInstance().getApi();
Call<List<model_doc>> calldoc=apiServices.getList2("ll0004");
calldoc.enqueue(new Callback<List<model_doc>>() {
#Override
public void onResponse(Call<List<model_doc>> call, Response<List<model_doc>> response) {
datalist2.postValue(response.body());
}
#Override
public void onFailure(Call<List<model_doc>> call, Throwable t) {
datalist2.postValue(null);
Log.e("Error :",t.getMessage());
}
});
}
}
///////////////////main model
public class model_doc {
String status,msg;
ArrayList<Data> data;
public model_doc(String status, String msg, ArrayList<Data> data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public String getStatus() {
return status;
}
public String getMsg() {
return msg;
}
public ArrayList<Data> getData() {
return data;
}
public static class Data {
String doctor_id;
String doctor_name;
String proposed_date;
String date;
// Getters setters
public Data(String doctor_id, String doctor_name, String proposed_date, String date) {
this.doctor_id = doctor_id;
this.doctor_name = doctor_name;
this.proposed_date = proposed_date;
this.date = date;
}
public String getDoctor_id() {
return doctor_id;
}
public String getDoctor_name() {
return doctor_name;
}
public String getProposed_date() {
return proposed_date;
}
public String getDate() {
return date;
}
}
}
////api interface
#FormUrlEncoded
#POST("doctor_list")
Call<List<model_doc>>getList2(
#Field("clinic_id") String clinic_id
);
//////////////////controller
public class apiController {
private static final String url="https://xyz.in/api/";
private static apiController clientObject;
private static Retrofit retrofit;
apiController()
{
retrofit=new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public static synchronized apiController getInstance(){
if(clientObject==null)
clientObject=new apiController();
return clientObject;
}
public apiSet getApi(){
return retrofit.create(apiSet.class);
}
}
////////////recycler adapter, made some changes in main model for nested data could handle it to adapter
public class todayDoctorAdapter extends RecyclerView.Adapter<todayDoctorAdapter.viewholder>
{
List<model_doc> datalist2;
public todayDoctorAdapter(List<model_doc> list){
this.datalist2=list;}
public void updateList(List<model_doc>list){
this.datalist2=list;
notifyDataSetChanged();
}
#NonNull
#Override
public todayDoctorAdapter.viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType){
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_doctors,parent,false);
return new todayDoctorAdapter.viewholder(view);
}
#Override
public void onBindViewHolder(#NonNull todayDoctorAdapter.viewholder holder, int position){
holder.doctor_name.setText(String.format("Dr.%s", datalist2.get(position).getDoctor_app()));
holder.proposed_date.setText(String.format("Apt: %s","TODAY"));
String doc=datalist2.get(position).getDoctor_app();
holder.cv.setOnClickListener(
new View.OnClickListener(){
#Override
public void onClick(View arg0) {
Intent intent = new Intent(arg0.getContext(), PatientsUnderDoctor.class);
intent.putExtra("doc_name", doc);
arg0.getContext().startActivity(intent);
}
});
}
#Override
public int getItemCount(){
if (this.datalist2!=null){
return this.datalist2.size();
}
return 0;
}
public static class viewholder extends RecyclerView.ViewHolder{
TextView doctor_name,proposed_date;
CardView cv;
public viewholder(#NonNull View itemView) {
super(itemView);
doctor_name=itemView.findViewById(R.id.drName);
proposed_date=itemView.findViewById(R.id.apptDate);
cv=itemView.findViewById(R.id.cv_patient);
}
}
}
//////////////////json data look like this
{
"status": "success",
"msg": "Found",
"data": [
{
"doc_code": "jhjh0001",
"app_date": "2022-09-13",
"doc_name": "kjk",
"count": 1
}
]
}

Recycleview not populated with JSON and Retrofit?

I am making a simple app in which the user will able to search for books by its name, with google.com book api. For now, I wish to present a list of books with android in their name. I am doing it with Retrofit2 and RecycleView, but nothing is showing.
MainActivity:
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
KnjigaAdapter knjigaAdapter;
List<KnjigaModel> listaKnjiga;
public static final String BASE_URL = "https://www.googleapis.com/books/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uzmiKomentare();
}
public void uzmiKomentare() {
Gson gson = new GsonBuilder().serializeNulls().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
KnjigaApi knjigaApi = retrofit.create(KnjigaApi.class);
final Call<KnjigaModel> pozivZaListuKnjiga = knjigaApi.getKnjige("android");
pozivZaListuKnjiga.enqueue(new Callback<KnjigaModel>() {
#Override
public void onResponse(Call<KnjigaModel> call, Response<KnjigaModel> response) {
if (!response.isSuccessful()) {
return;
}
//generateRecycleView(WHAT TO PUT HERE!!!!);
}
#Override
public void onFailure(Call<KnjigaModel> call, Throwable t) {
Log.d("MainActivity:", t.getMessage());
}
});
}
private void generateRecycleView(List<KnjigaModel> knjige) {
listaKnjiga = new ArrayList<>();
recyclerView = findViewById(R.id.recycleview);
knjigaAdapter = new KnjigaAdapter(this, knjige);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(knjigaAdapter);
if (knjigaAdapter.getItemCount() == 0){
Log.i("List is empty: ","YES");
}
else {
Log.i("list is empty: ","No");
}
}
}
api inteface:
public interface KnjigaApi {
#GET("v1/volumes")
Call<KnjigaModel> getKnjige(#Query("q") String knjiga);
}
model class:
public class KnjigaModel {
#SerializedName("title")
#Expose
private String imeKnjige;
#SerializedName("authors")
#Expose
private String imeAutora;
#SerializedName("thumbnail")
#Expose
private String slikaKnjige;
public KnjigaModel(String imeKnjige, String imeAutora,String slikaKnjige) {
this.imeKnjige = imeKnjige;
this.imeAutora = imeAutora;
this.slikaKnjige = slikaKnjige;
}
public String getImeKnjige() {
return imeKnjige;
}
public String getImeAutora() {
return imeAutora;
}
public String getSlikaKnjige() {
return slikaKnjige;
}
}
and my adapter:
public class KnjigaAdapter extends RecyclerView.Adapter<KnjigaAdapter.KomentariViewHolder> {
private List<KnjigaModel> listaKnjiga;
private LayoutInflater inflater;
private Context context;
public KnjigaAdapter(Context context, List<KnjigaModel> listaKnjiga) {
this.listaKnjiga = listaKnjiga;
this.context = context;
}
#Override
public KomentariViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(context);
// Inflate the custom layout
View postView = inflater.inflate(R.layout.single_item, parent, false);
// Return a new holder instance
return new KomentariViewHolder(postView);
}
#Override
public void onBindViewHolder(KomentariViewHolder holder, int position) {
KnjigaModel knjige = listaKnjiga.get(position);
holder.naslovKnjige.setText(knjige.getImeKnjige());
holder.imeAutora.setText(knjige.getImeAutora());
Glide.with(context)
.load(knjige.getSlikaKnjige())
.into(holder.slikaKnjige);
}
#Override
public int getItemCount() {
return listaKnjiga.size();
}
public class KomentariViewHolder extends RecyclerView.ViewHolder {
private TextView naslovKnjige;
private TextView imeAutora;
private ImageView slikaKnjige;
public KomentariViewHolder(View itemView) {
super(itemView);
naslovKnjige = itemView.findViewById(R.id.ime_knjige);
imeAutora = itemView.findViewById(R.id.autor_knjige);
slikaKnjige = itemView.findViewById(R.id.sika_korica);
}
}
}
my JSON format:
https://www.googleapis.com/books/v1/volumes?q=android
First of all, I strongly recommend to use RxJava for asynchronous requests, though it's totally optional.
Your Problem:
Your "getKnjige" Method returns only ONE Model, though the endpoint is named volumes (plural), you need to wrap your KnjigaModel in a class like
data class KnjigaResponse(val items: List<KnjigaModel>)
(Kotlin for simplicity, you can also generate a Java class with a single member volumes member that holds a list of KnjigaModel)
In addition, your model is wrong. authors is not a string, but a List of Strings, and "thumbnail" is wrapped in an "imageLinks" Object, and title is wrapped in a volumeInfo Object.
Your retrofit interface then would look like this:
public interface KnjigaApi {
#GET("v1/volumes")
Call<KnjigaResponse> getKnjige(#Query("q") String knjiga);
Request:
final Call<KnjigaResponse> pozivZaListuKnjiga = knjigaApi.getKnjige("android");
pozivZaListuKnjiga.enqueue(new Callback<KnjigaResponse>() {
#Override
public void onResponse(Call<KnjigaResponse> call, Response<KnjigaResponse> response) {
if (!response.isSuccessful()) {
return;
}
generateRecycleView(response.items);
}
#Override
public void onFailure(Call<KnjigaResponse> call, Throwable t) {
Log.d("MainActivity:", t.getMessage());
}
});

Android Retrofit 2.1.0 Response.body() is null, status code is 404

I am trying to make a call to this api and am having difficulty as the response.body() is returning null.
http://demo.museum.vebrary.vn/api/stuff/getall
I want to get stuff name of list and show to my recyclerview.
My model:
public class SOAnswersResponse {
#SerializedName("StuffModels")
#Expose
private List<StuffModel> stuffModels = null;
public List<StuffModel> getStuffModels() {
return stuffModels;
}
public void setStuffModels(List<StuffModel> stuffModels) {
this.stuffModels = stuffModels;
}
and
public class StuffModel {
#SerializedName("STUFFID")
#Expose
private Integer sTUFFID;
#SerializedName("STUFFCODE")
#Expose
private String sTUFFCODE;
#SerializedName("STUFFNAME")
#Expose
private String sTUFFNAME;
#SerializedName("STUFFNOTE")
#Expose
private String sTUFFNOTE;
#SerializedName("STUFFORDER")
#Expose
private Integer sTUFFORDER;
#SerializedName("CUSTOMERID")
#Expose
private String cUSTOMERID;
#SerializedName("EXHIBITS")
#Expose
private List<Object> eXHIBITS = null;
Json response
{
"StuffModels":[
{
"STUFFID":2,
"STUFFCODE":"Gi",
"STUFFNAME":"Giấy",
"STUFFNOTE":"",
"STUFFORDER":2,
"CUSTOMERID":"CAMAU",
"EXHIBITS":[
]
},
ApiUtils Class
public class ApiUtils {
private ApiUtils() {
}
public static final String BASE_URL = "http://demo.museum.vebrary.vn/api/";
public static SOService getSOService() {
return RetrofitClient.getClient(BASE_URL).create(SOService.class);
}
}
Service interface
public interface SOService {
#GET("/stuff/getall")
Call<SOAnswersResponse> getAnswers();
}
RetrofitClient Class
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
My RecyclerView adapter
public class CategogyNameRecyclerViewAdapter extends RecyclerView.Adapter<CategogyNameRecyclerViewAdapter.ViewHolder> {
private List<StuffModel> mItems;
private Context mContext;
private PostItemListener mItemListener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView titleTv;
PostItemListener mItemListener;
public ViewHolder(View itemView, PostItemListener postItemListener) {
super(itemView);
titleTv = itemView.findViewById(R.id.tvListMenuCategogy);
this.mItemListener = postItemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
StuffModel item = getItem(getAdapterPosition());
this.mItemListener.onPostClick(item.getSTUFFID());
notifyDataSetChanged();
}
}
public CategogyNameRecyclerViewAdapter(Context context, List<StuffModel> posts, PostItemListener itemListener) {
mItems = posts;
mContext = context;
mItemListener = itemListener;
}
#Override
public CategogyNameRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View postView = inflater.inflate(R.layout.item_list_text, parent, false);
ViewHolder viewHolder = new ViewHolder(postView, this.mItemListener);
return viewHolder;
}
#Override
public void onBindViewHolder(CategogyNameRecyclerViewAdapter.ViewHolder holder, int position) {
StuffModel item = mItems.get(position);
TextView textView = holder.titleTv;
textView.setText(item.getSTUFFNAME());
}
#Override
public int getItemCount() {
return mItems.size();
}
public void updateAnswers(List<StuffModel> items) {
mItems = items;
notifyDataSetChanged();
}
private StuffModel getItem(int adapterPosition) {
return mItems.get(adapterPosition);
}
public interface PostItemListener {
void onPostClick(long id);
}
}
And my main activity
public class Testttt extends AppCompatActivity {
private CategogyNameRecyclerViewAdapter mAdapter;
private RecyclerView mRecyclerView;
private SOService mService;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView(R.layout.test );
mService = ApiUtils.getSOService();
mRecyclerView = (RecyclerView) findViewById(R.id.rcvCategogyNameMenuTest);
mAdapter = new CategogyNameRecyclerViewAdapter(this, new ArrayList<StuffModel>(0), new CategogyNameRecyclerViewAdapter.PostItemListener() {
#Override
public void onPostClick(long id) {
Toast.makeText(Testttt.this, "Post id is" + id, Toast.LENGTH_SHORT).show();
}
});
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
mRecyclerView.addItemDecoration(itemDecoration);
loadAnswers();
}
public void loadAnswers() {
mService.getAnswers().enqueue(new Callback<SOAnswersResponse>() {
#Override
public void onResponse(Call<SOAnswersResponse> call, Response<SOAnswersResponse> response) {
Toast.makeText(Testttt.this, "333333333333333333"+response.body(), Toast.LENGTH_SHORT).show();
if(response.isSuccessful()) {
mAdapter.updateAnswers(response.body().getStuffModels());
Log.d("AnswersPresenter", "posts loaded from API");
}else {
int statusCode = response.code();
}
}
#Override
public void onFailure(Call<SOAnswersResponse> call, Throwable t) {
showErrorMessage();
Log.d("AnswersPresenter", "error loading from API");
}
});
}
public void showErrorMessage() {
Toast.makeText(this, "Error loading posts", Toast.LENGTH_SHORT).show();
}
}
The first thing that came in my mind:
Your
public static final String BASE_URL = "http://demo.museum.vebrary.vn/api/";
has a "/" at the the end and your
#GET("/stuff/getall")
Call<SOAnswersResponse> getAnswers();
starts with a "/". So there is a double backslash in the url that might leads to the 404 code. Does this solve the problem?
When i call your URL i receive XML. Maybe the API is not configured correctly?
Change your Service interface
public interface SOService {
#GET("stuff/getall")
Call<SOAnswersResponse> getAnswers();
}
it occurred because you have use start with backslash it already added in your base url

Android retrofit call bad behavior

Good day, so my problem as follows.
When I initialize the retrofit call it has following flow.
1.In the Presenterclass, it goes to getData method.
2.Then it goes to Interactorclass and creates a instance of itself.
3.Then it starts to fetch data from getMovieList method.
4.When it gets to call.enqueue it says OnDataCallback is null.
5.Goes back to Presenter and returns a null List.
6.It resumes call.enqueue does the api call as required.
7.Returns to Presenter and returns the List of objects.
I have tried so many things but non seem to work, maybe I'm understanding something incorrectly ,any help would be appreciated thanks.
Interactor Class.
public class MovieListInteractor implements IMovieContarctor.MovieListInteractor {
private InteractorListener mListener;
private List<MovieListModel> mList;
public MovieListInteractor(InteractorListener mListener) {
this.mListener = mListener;
}
public int getMovieSize() {
return mList.size();
}
#Override
public String getMoviePosterPath(int pos) {
return mList.get(pos).getPosterPath();
}
#Override
public MovieListModel getMovie(int pos) {
return mList.get(pos);
}
#Override
public List<MovieListModel> getMovieList() {
if (mList == null)
mList = new ArrayList<>();
ServerMovieCall mCall = new ServerMovieCall();
mCall.getMovieList(new IOnDataCallback<List<MovieListModel>>() {
#Override
public void onSuccess(List<MovieListModel> data) {
mList.addAll(data);
}
#Override
public void onFailure(String message) {
Log.d(TAG, "onFailure: " + message);
}
});
return mList;
}
}
Presenter class
public class MovieListPresenter implements IMovieContarctor.MovieListPresenter, InteractorListener {
private MovieListFragment mView;
private MovieListInteractor mInteractor;
private List<MovieListModel> mList;
public MovieListPresenter(MovieListFragment mView) {
this.mView = mView;
mInteractor = new MovieListInteractor(this);
getData();
}
//TODO: Add functionality so that the view could call mView.refreshAdapterList
//TODO: And from the view - adapter.notifiyDataSetChange;
#Override
public void onSuccess(List<MovieListModel> data, String msg) {
mView.onDataChange(data, msg);
}
#Override
public void onFailure(String msg) {
mView.onDataFailure(msg);
}
#Override
public void bindAtPosition(int position, MovieListViewHolder holder) {
holder.setValue(mInteractor.getMovie(position));
}
#Override
public void getData() {
mList = mInteractor.getMovieList();
}
#Override
public String getMoviePosterPath(int pos) {
return mInteractor.getMoviePosterPath(pos);
}
#Override
public int getSize() {
return mInteractor.getMovieSize();
}
}
Adapter
public class MovieListAdapter extends RecyclerView.Adapter<MovieListViewHolder> {
private MovieListPresenter mPresenter;
private Context ctx;
public MovieListAdapter(MovieListPresenter mPresenter, Context context) {
this.mPresenter = mPresenter;
this.ctx = context;
}
#Override
public MovieListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MovieListViewHolder(LayoutInflater.from(ctx).inflate(R.layout.main_view_movie_list, parent, false));
}
#Override
public void onBindViewHolder(MovieListViewHolder holder, int position) {
mPresenter.bindAtPosition(position, holder);
String image_url = IMAGE_URL_BASE_PATH + mPresenter.getMoviePosterPath(position);
Picasso.with(ctx).load(image_url).placeholder(android.R.drawable.sym_def_app_icon)
.error(android.R.drawable.sym_def_app_icon).into(holder.mImage);
}
#Override
public int getItemCount() {
return mPresenter.getSize();
}
}
MovieCall class
public class ServerMovieCall {
private Retrofit retrofit;
private static ServerMovieCall mInstance;
private Context ctx;
public static ServerMovieCall getInstance() {
if (mInstance == null) {
mInstance = new ServerMovieCall();
}
return mInstance;
}
public ServerMovieCall() {
configureClient();
}
private void configureClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(logging).addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HttpUrl url = request.url().newBuilder().addQueryParameter("api_key", Constants.API_KEY).build();
request = request.newBuilder().url(url).build();
return chain.proceed(request);
}
}).build();
retrofit = new Retrofit.Builder().baseUrl(Constants.API_BASE_URL).client(client)
.addConverterFactory(GsonConverterFactory.create()).build();
}
public void getMovieList(final IOnDataCallback<List<MovieListModel>> onDataCallback) {
IServerMovieApiHelper iMovieReviewApiService = retrofit.create(IServerMovieApiHelper.class);
Call<MovieListResponse> call = iMovieReviewApiService.getMovieList();
call.enqueue(new Callback<MovieListResponse>() {
#Override
public void onResponse(Call<MovieListResponse> call, Response<MovieListResponse> response) {
if (response.isSuccessful()) {
onDataCallback.onSuccess(response.body().getMovies());
} else {
onDataCallback.onFailure(response.message());
}
}
#Override
public void onFailure(Call<MovieListResponse> call, Throwable t) {
onDataCallback.onFailure(t.getLocalizedMessage());
}
});
}
Contract interfaces
public interface IMovieContarctor {
public interface MovieListInteractor {
List<MovieListModel> getMovieList();
MovieListModel getMovie(int pos);
String getMoviePosterPath(int pos);
}
public interface MovieListPresenter {
void bindAtPosition(int position, MovieListViewHolder holder);
String getMoviePosterPath(int pos);
int getSize();
void getData();
}
public interface MovieListView {
void onDataChange(List<MovieListModel> data, String message);
void onDataFailure(String message);
}
}
DataCallback Listener.
public interface IOnDataCallback<T> {
void onSuccess(T data);
void onFailure(String message);
}
In Interactor class:
#Override
public List<MovieListModel> getMovieList() {
if (mList == null)
mList = new ArrayList<>();
ServerMovieCall mCall = new ServerMovieCall();
mCall.getMovieList(new IOnDataCallback<List<MovieListModel>>() {
#Override
public void onSuccess(List<MovieListModel> data) {
mList.addAll(data);
mListener.onSuccess(mList, "Your message");
}
#Override
public void onFailure(String message) {
Log.d(TAG, "onFailure: " + message);
}
});
return mList;
}
In Presenter class:
#Override
public void onSuccess(List<MovieListModel> data, String msg) {
mList = data;
mView.onDataChange(data, msg);
}

Android Recyclerview, okhttp, receiving an java.lang.ClassCastException error

I am trying to load data into my recyclerview via url okhttp calls, and I am receiving the following error:
"java.lang.ClassCastException: SearchActivity cannot be cast to SearchForBarbershop$BarbershopRequesterResponse"
Here are the classes.
SearchActivity:
public class SearchActivity extends AppCompatActivity {
private RecyclerAdapter mAdapter;
private RecyclerView mRecyclerView;
private LinearLayoutManager mLinearLayoutManager;
private ArrayList<Barbershop> barbershopList;
private SearchForBarbershop searchForBarbershop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
barbershopList = new ArrayList<>();
mAdapter = new RecyclerAdapter(barbershopList);
mRecyclerView.setAdapter(mAdapter);
setRecyclerViewScrollListener();
searchForBarbershop = new SearchForBarbershop(this);
}
#Override
protected void onStart() {
super.onStart();
if (barbershopList.size() == 0) {
requestShop();
}
}
private int getLastVisibleItemPosition() {
return mLinearLayoutManager.findLastVisibleItemPosition();
}
private void setRecyclerViewScrollListener() {
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
int totalItemCount = mRecyclerView.getLayoutManager().getItemCount();
if (!searchForBarbershop.isLoadingData() && totalItemCount == getLastVisibleItemPosition() + 1) {
requestShop();
}
}
});
}
private void requestShop() {
try {
searchForBarbershop.getBarbershop();
} catch (IOException e) {
e.printStackTrace();
}
}
//#Override
public void receivedNewShop(final Barbershop newBarbershop) {
runOnUiThread(new Runnable() {
#Override
public void run() {
barbershopList.add(newBarbershop);
mAdapter.notifyItemInserted(barbershopList.size());
}
});
}
}
SearchForBarbershop:
public class SearchForBarbershop {
public interface BarbershopRequesterResponse {
void receivedNewBarbershop(Barbershop barbershop);
}
private BarbershopRequesterResponse barbershopRequesterResponse;
private OkHttpClient client;
private boolean isLoadingData;
public boolean isLoadingData() { return isLoadingData; }
public SearchForBarbershop (Activity listeningActivity) {
client = new OkHttpClient();
isLoadingData = false;
barbershopRequesterResponse = (BarbershopRequesterResponse) listeningActivity;
}
public void getBarbershop() throws IOException {
String url = "http://pubapi.yp.com/search-api/search/devapi/search?searchloc=30043&term=barbers&format=json&sort=distance&radius=50&listingcount=20&key=gmj3x7mhsh";
Request request = new Request.Builder().url(url).build();
isLoadingData = true;
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
isLoadingData = false;
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
JSONObject object = new JSONObject(response.body().string());
Barbershop receivedShop = new Barbershop(object);
barbershopRequesterResponse.receivedNewBarbershop(receivedShop);
isLoadingData = false;
} catch (JSONException e) {
isLoadingData = false;
e.printStackTrace();
}
}
});
}
}
Barbershop:
public class Barbershop{
private String name;
private String city;
public Barbershop(JSONObject barbershopJSON) {
try {
JSONArray businessArray = barbershopJSON.getJSONObject("searchResult").getJSONObject("searchListings").getJSONArray("searchListing");
for(int i = 0; i < businessArray.length(); i++) {
//Parse JSON and assign to variables
JSONObject business_object_1 = businessArray.getJSONObject(i);
String primaryc = business_object_1.getString("primaryCategory");
//Check to make sure the main category is "Barbers"
if((primaryc).equals("Barbers")) {
name = business_object_1.getString("businessName");
city = business_object_1.getString("city");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public String getCity() {
return city;
}
public String getName() {
return name;
}
}
RecyclerAdapter:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ShopHolder> {
private ArrayList<Barbershop> mbarbershops;
public RecyclerAdapter(ArrayList<Barbershop> barbershops) {
mbarbershops = barbershops;
}
#Override
public RecyclerAdapter.ShopHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cardview_barber_search, parent, false);
return new ShopHolder(inflatedView);
}
#Override
public void onBindViewHolder(RecyclerAdapter.ShopHolder holder, int position) {
Barbershop itemBarbershop = mbarbershops.get(position);
holder.bindShop(itemBarbershop);
}
#Override
public int getItemCount() {
return 0;
}
public static class ShopHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mName;
private TextView mCity;
public ShopHolder(View view) {
super(view);
mName = (TextView) view.findViewById(R.id.textViewName);
mCity = (TextView) view.findViewById(R.id.textViewCity);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
public void bindShop(Barbershop barbershop) {
mName.setText(barbershop.getName());
mCity.setText(barbershop.getCity());
}
}
}
It can't be cast because it doesn't implement that interface. Your commented-out #override statement should be a clue for you here.
Change it to:
public class SearchActivity extends AppCompatActivity
implements SearchForBarbershop.BarbershopRequesterResponse {
....
And don't forget to remove the comment for method you implemented:
#Override
public void receivedNewShop(final Barbershop newBarbershop) {
....
I think you need change constructor SearchForBarbershop
BarbershopRequesterResponse listener;
Context context
public SearchForBarbershop (Context context,BarbershopRequesterResponse listener) {
client = new OkHttpClient();
isLoadingData = false;
this.context = context;
this.listener = listener;
}
And change in SearchActivity
searchForBarbershop = new SearchForBarbershop(SearchActivity.this, this);

Categories

Resources