recyclerView missing error in Android Studio - java

I'm a beginner programmer and I'm trying to receive data from the server using node.js and display the list on Android Studio but I keep having the following error:
E/RecyclerView: No adapter attached; skipping layout
D/HistoryActivity: HistoryResponse{result=[com.sooryong.loginexample.data.HistoryData#3303f3c, com.sooryong.loginexample.data.HistoryData#33764c5]}
D/AndroidRuntime: Shutting down VM
As you can see, I can't recall my list properly as well and I don't know how to fix it. Here are my codes:
public interface ServiceApi {
#POST("/user/login")
Call<LoginResponse> userLogin(#Body LoginData data);
#POST("/user/join")
Call<JoinResponse> userJoin(#Body JoinData data);
#GET("/test/history")
Call<HistoryResponse> getData();
}
HistoryData.java
public class HistoryData {
#SerializedName("eventID")
private int eventID;
#SerializedName("eventType")
private String eventType;
#SerializedName("eventDate")
private String eventDate;
#SerializedName("userID")
private int userID;
#SerializedName("sensorID")
private String sensorID;
public HistoryData(int eventID, String eventType, String eventDate, int userID, String sensorID) {
super();
this.eventID = eventID;
this.eventType = eventType;
this.eventDate = eventDate;
this.userID = userID;
this.sensorID = sensorID;
}
public int getEventID() {
return eventID;
}
public String getEventType() {
return eventType;
}
public String getEventDate() { return eventDate; }
public int getUserID() {
return userID;
}
public String getSensorID() { return sensorID; }
}
HistoryResponse.java
public class HistoryResponse {
#SerializedName("code")
public String code;
#SerializedName("message")
public String message;
#SerializedName("result")
public List<HistoryData> result;
#Override
public String toString() {
return "HistoryResponse{" + "result=" + result +'}';
}
}
HistoryActivity.java
public class HistoryActivity extends AppCompatActivity {
HistoryResponse dataList;
List<HistoryData> dataInfo;
private RecyclerView recyclerView;
private RecyclerAdapter recyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
recyclerView = findViewById(R.id.recyclerView);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
ServiceApi apiInterface = RetrofitClient.getClient().create(ServiceApi.class);
Call<HistoryResponse> call = apiInterface.getData();
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
Log.d("Response", dataList.toString());
dataInfo = dataList.result;
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
}
}
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>{
private Context c;
private List<HistoryData> dataList;
public RecyclerAdapter(Context c, List<HistoryData> dataList) {
this.c = c;
this.dataList = dataList;
}
#NonNull
#Override
public RecyclerAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(c).inflate(R.layout.recycler_view, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerAdapter.MyViewHolder holder, int position) {
holder.id.setText(dataList.get(position).getSensorID());
holder.type.setText("" + dataList.get(position).getEventType());
holder.date.setText("" + dataList.get(position).getEventDate());
}
#Override
public int getItemCount() {
return (dataList == null) ? 0 : dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView id;
TextView type;
TextView date;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
id = (TextView)itemView.findViewById(R.id.sensorID);
type = (TextView)itemView.findViewById(R.id.eventType);
date = (TextView)itemView.findViewById(R.id.eventDate);
}
}
}
I don't think the data is being initialized properly inside the RecyclerAdapter class. Is it because I couldn't load the data properly from the server?

I ever face the same issue similiar to this.
What I've done was: initialize the adapter once only the activity created:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
initAdapter();
....
}
private void initAdapter() {
//The adapter should create once in onCreate
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext, LinearLayoutManager.VERTICAL, false);
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
Then when in callback result: you can clear the previous data before reload to the adapter:
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
dataInfo.clear(); // <- here we clear all previous data before reload result to the adapter.
dataInfo = dataList.result;
recyclerAdapter.notifyDataSetChanged()
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
Hope this help.

Related

display data into recycler view using mutiple api request and one adapter

I'm using RecyclerView to display some data from an API response using one adapter
but i want to display data from more then one API response (so i need to make more then one get request)
this is my adapter :
private Context Context1;
private List<TraitementTicketModel> followuplist;
public FollowupAdapter(Context mContext, List<TraitementTicketModel> followuplist) {
this.Context1 = mContext;
this.followuplist = followuplist;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v;
LayoutInflater layoutInflater=LayoutInflater.from(Context1);
v=layoutInflater.inflate(R.layout.followupitem,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.users_id.setText(followuplist.get(position).getUsers_id());
holder.date.setText(followuplist.get(position).getDate());
holder.titre.setText(followuplist.get(position).getTitre());
holder.content.setText(html2text(followuplist.get(position).getContent()));
}
#Override
public int getItemCount() {
return followuplist.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
TextView users_id;
TextView date;
TextView content;
TextView titre;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
users_id=itemView.findViewById(R.id.user_id_followup);
date =itemView.findViewById(R.id.date_followup);
content=itemView.findViewById(R.id.contenu_followup);
titre=itemView.findViewById(R.id.titre_followup);
}
}
public static String html2text(String html) {
return Jsoup.parse(Jsoup.parse(html).text()).text();
}
and this is the code to display the data into the recyclerview
SharedPreferences sp = getApplicationContext().getSharedPreferences("tokenPref", Context.MODE_PRIVATE);
String sestoken = sp.getString("token", "");
SharedPreferences sp1 = getApplicationContext().getSharedPreferences("idPref", Context.MODE_PRIVATE);
String id = sp1.getString("id", "");
Retrofit retrofit = RetrofitInstance.getRetrofitInstance();
final Api api = retrofit.create(Api.class);
Call<List<TraitementTicketModel>> call = api.getfollowup(id, sestoken);
call.enqueue(new Callback<List<TraitementTicketModel>>() {
#Override
public void onResponse(Call<List<TraitementTicketModel>> call, Response<List<TraitementTicketModel>> response) {
if (!response.isSuccessful()) {
Toast.makeText(getApplicationContext(),"Something is wrong !! ",Toast.LENGTH_LONG).show();
Log.e("TAG", "onResponse: something is wrong");
}
List<TraitementTicketModel> followups = response.body();
for (TraitementTicketModel followup : followups) {
followuplist.add(followup);
}
followuplist.add(firstfollowup());
PutDataIntoRecyclerView(followuplist);
}
#Override
public void onFailure(Call<List<TraitementTicketModel>> call, Throwable t) {
}
});
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
FollowupAdapter adapter =new FollowupAdapter(this,followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}
so is it possible to display data into one recylerview using one adapter and more then one API request .
Edit :
this is the TraitementTicketModel class :
public class TraitementTicketModel {
private String users_id;
private String date;
private String content;
private String titre;
public TraitementTicketModel(String users_id, String date, String content, String titre) {
this.users_id = users_id;
this.date = date;
this.content = content;
this.titre = titre;
}
public String getTitre() {
return titre;
}
public String getUsers_id() { return users_id; }
public String getDate() { return date; }
public String getContent() {
return content;
}
}
when i try to sort the list by date before i put it in the adapter the data doesn't show .
in the adapter class :
public List addToList(List<TraitementTicketModel> list) {
this.followuplist.addAll(list);
notifyDataSetChanged();
Collections.sort(followuplist, new Comparator<TraitementTicketModel>() {
#Override
public int compare(TraitementTicketModel o1, TraitementTicketModel o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return this.followuplist;
}
in the main activity :
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
Sort(followuplist);
if (adapter == null) {
adapter=new FollowupAdapter(this,followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}else {
adapter=new FollowupAdapter(this,adapter.addToList(followuplist));
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}
}
private List Sort (List<TraitementTicketModel> datalist){
Collections.sort(datalist, new Comparator<TraitementTicketModel>() {
#Override
public int compare(TraitementTicketModel o1, TraitementTicketModel o2) {
return o2.getDate().compareTo(o1.getDate());
}
});
return datalist;
}
so is it possible to display data into one recylerview using one adapter and more then one api request
Yes it's possible if all API responses have the same data scheme as the adapter list.
You can add a method in the adapter that accumulates the current list:
public addToList(List<TraitementTicketModel> list) {
this.followuplist.addAll(list);
notifyDataSetChanged();
}
Then make the adapter as a class field, to only be instantiated for the first response, and reuse it in further responses:
FollowupAdapter mAdapter;
Then if the adapter not instantiated, instantiate it with the initial list, otherwise accumulate the list:
private void PutDataIntoRecyclerView(List<TraitementTicketModel> followuplist) {
if (mAdapter == null) {
mAdapter = new FollowupAdapter(this, followuplist);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
} else {
mAdapter.addToList(followuplist);
}
}

Having problem to fetching file from firestore recycle view [duplicate]

This question already has an answer here:
Firebase Android ListView not being displayed
(1 answer)
Closed 1 year ago.
I am an android developer beginner, I am having a problem fetch files from firestore recycle view in the main activity but I can fetch files from fragments.
This is my main activity
public class FoodInfoActivity extends AppCompatActivity {
RecyclerView recyclerView1,recyclerView2;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference notebookRef;
private NoteAdapter adapter;
FirebaseAuth fAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_food_info);
fAuth = FirebaseAuth.getInstance();
setUpRecyclerView();
}
private void setUpRecyclerView() {
notebookRef = db.collection("FoodInside");
Query query = notebookRef;
FirestoreRecyclerOptions<FoodAdapter> options = new FirestoreRecyclerOptions.Builder<FoodAdapter>()
.setQuery(query, FoodAdapter.class)
.build();
adapter = new NoteAdapter(options);
RecyclerView recyclerView = findViewById(R.id.fi);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
}
This is my Note adapter where i use model class to fetch file
public class NoteAdapter extends FirestoreRecyclerAdapter<FoodAdapter, NoteAdapter.NoteHolder> {
public NoteAdapter(#NonNull FirestoreRecyclerOptions<FoodAdapter> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull NoteHolder holder, int position, #NonNull FoodAdapter foodAdapter) {
holder.textViewTitle.setText(foodAdapter.getRestaurant());
holder.textViewDescription.setText(foodAdapter.getItem());
holder.textViewPriority.setText(String.valueOf(foodAdapter.getPrice()));
}
#NonNull
#Override
public NoteHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_recycle_layout,
parent, false);
return new NoteHolder(v);
}
class NoteHolder extends RecyclerView.ViewHolder {
TextView textViewTitle;
TextView textViewDescription;
TextView textViewPriority;
public NoteHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.textView95a);
textViewDescription = itemView.findViewById(R.id.textView123a);
textViewPriority = itemView.findViewById(R.id.textView124a);
}
}
}
This is my adapter class ,
public class FoodAdapter {
String Restaurant;
String Item;
String Price;
String item_id;
public FoodAdapter() {
}
public FoodAdapter(String restaurant, String item, String price,String item_id) {
Restaurant = restaurant;
Item = item;
Price = price;
this.item_id = item_id;
}
public String getRestaurant() {
return Restaurant;
}
public void setRestaurant(String restaurant) {
Restaurant = restaurant;
}
public String getItem() {
return Item;
}
public void setItem(String item) {
Item = item;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
public String getItem_id() {
return item_id;
}
public void setItem_id(String item_id) {
this.item_id = item_id;
}
}
Why it is not working in main activity but work fragment. I am just afraid. and tired...working on the project. so need solution of this problem
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
Add this line to main activity.

How can I hide an ImageView on my RecyclerView for certain items based on a particular condition?

I have a RecyclerView with an ImageView being a part of the items. I want to hide the ImageView from an item in the RecyclerView if a certain condition is met. How can I do that? I am attaching the image of how I want it to look like.
I am just defining the ImageViews in my xml layout file, so I cannot figure out how to actually remove it based on a certain condition in my android activity. I am attaching the code for the adapter class and my activity as well.
Here is the code for my adapter class
Adapter Class
public class ReportAdapter extends RecyclerView.Adapter<ReportAdapter.ReportViewHolder> {
private ArrayList<ReportItem> reportlist;
private OnItemClickListener mListener;
private Context mContext;
public ReportAdapter(ArrayList<ReportItem> reportlist, Context context) {
this.reportlist = reportlist;
this.mContext = context;
}
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class ReportViewHolder extends RecyclerView.ViewHolder {
public TextView departureDate;
public TextView flightNumber;
public View relativelayout;
public ReportViewHolder(#NonNull View itemView, OnItemClickListener listener, Context context) {
super(itemView);
departureDate = itemView.findViewById(R.id.departureDaterecyclerview);
flightNumber = itemView.findViewById(R.id.flightnumberrecyclerview);
relativelayout = itemView.findViewById(R.id.relativeLayoutReports);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null) {
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
#NonNull
#Override
public ReportViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.report_listing_item, parent, false);
ReportViewHolder rvh= new ReportViewHolder(v,mListener,mContext);
return rvh;
}
#SuppressLint("ResourceAsColor")
#Override
public void onBindViewHolder(#NonNull ReportViewHolder holder, int position) {
ReportItem currentItem = reportlist.get(position);
if(position%2==0){
holder.relativelayout.setBackgroundColor(mContext.getResources().getColor(R.color.reportlistingteal));
} else {
holder.relativelayout.setBackgroundColor(mContext.getResources().getColor(R.color.reportlistinglightteal));
}
holder.departureDate.setText((currentItem.getDepartureDate()));
holder.flightNumber.setText(currentItem.getFlightNumber());
}
Here is the code for my activity file
Activity file
public class ReportListingActivity extends AppCompatActivity {
private Button uploadAllBtn;
private EditText searchFlights;
private RecyclerView mRecyclerView;
private ReportAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
ArrayList<ReportItem> reportitems = new ArrayList<>();
private FlightViewModel flightViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report_listing);
uploadAllBtn = findViewById(R.id.uploadAllReports);
searchFlights = findViewById(R.id.searchFlightText);
mRecyclerView = findViewById(R.id.recyclerView);
flightViewModel = new ViewModelProvider(this).get(FlightViewModel.class);
flightViewModel.getAllFlights().observe(this, new Observer<List<Flight>>() {
#Override
public void onChanged(List<Flight> flight_list) {
if (flight_list.size() == 0) return;
String flightno = flight_list.get(0).getFlightNumber();
String flightdate = flight_list.get(0).getDate();
String[] flight_details = new String[2];
flight_details[0]= flightno;
flight_details[1] = flightdate;
Log.v("pp", flight_details[0]);
for(int i = 0; i <flight_list.size();i++){
String flightnumber = flight_list.get(i).getFlightNumber();
String departuredate = flight_list.get(i).getDate();
reportitems.add(new ReportItem(flightnumber,departuredate));
}
mRecyclerView.getAdapter().notifyDataSetChanged();
flightViewModel.getAllFlights().removeObservers(ReportListingActivity.this);
}
});
mLayoutManager = new LinearLayoutManager(ReportListingActivity.this);
mAdapter = new ReportAdapter(reportitems, ReportListingActivity.this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
Report Item
public class ReportItem {
private String departureDate;
private String flightNumber;
public ReportItem(String departureDate, String flightNumber) {
this.departureDate = departureDate;
this.flightNumber = flightNumber;
}
public String getDepartureDate() {
return departureDate;
}
public String getFlightNumber() {
return flightNumber;
}
}
Add a boolean flag to your ReportItem class for each RecyclerView item. You will need to specify which rows show or hide this field when each item is created:
public class ReportItem {
private String departureDate;
private String flightNumber;
private Boolean showMailIcon;
public ReportItem(String departureDate, String flightNumber, Boolean showMailIcon) {
this.departureDate = departureDate;
this.flightNumber = flightNumber;
this.showMailIcon = showMailIcon
}
public String getDepartureDate() {
return departureDate;
}
public String getFlightNumber() {
return flightNumber;
}
public String getShowMailIcon() {
return showMailIcon;
}
}
Then update the onBindViewHolder() method override to use this flag to show/hide the ImageView:
#Override
public void onBindViewHolder(#NonNull ReportViewHolder holder, int position) {
ReportItem currentItem = reportlist.get(position);
if (currentItem.getShowMailIcon() == true) {
holder.mailIcon.setVisibility(View.VISIBLE);
} else {
holder.mailIcon.setVisibility(View.GONE);
}
//.......
}

recyclerview for chat app doesn't show any data or views

Hi I'm building chat app UI with android but it runs without showing any data or views,
I interact with a bot server that should return text after I send a text. I'm using retrofit for http connections.
the model class showing are the response from json
please help me and ask me any details you want
My adapter
public class MessageListAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Messages> data;
private Context mContext;
// constructor
public MessageListAdapter(List<Messages> data, Context mContext) {
this.data = data;
this.mContext = mContext;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
return new SentMessageHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.user_message, parent, false));
} else {
return new RecvdMessageHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.bot_message, parent, false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int type = getItemViewType(position);
Messages messages = data.get(position);
if (type == VIEW_TYPE_MESSAGE_SENT) {
SentMessageHolder sentMessageHolder = (SentMessageHolder) holder;
sentMessageHolder.messageBody.setText(messages.getText());
} else {
RecvdMessageHolder recvdMessageHolder = (RecvdMessageHolder) holder;
recvdMessageHolder.messageBody.setText(messages.getText());
}
}
public int getItemViewType(int position) {
Messages messages = data.get(position);
if (messages.getRecipientId() == ("default")) {
return VIEW_TYPE_MESSAGE_SENT;
} else
return VIEW_TYPE_MESSAGE_RECEIVED;
}
#Override
public int getItemCount() {
if (data != null) {
return data.size();
} else return 0;
}
class SentMessageHolder extends RecyclerView.ViewHolder {
public TextView messageBody;
public SentMessageHolder(View itemView) {
super(itemView);
messageBody = (TextView) itemView.findViewById(R.id.text_message_body);
}
}
class RecvdMessageHolder extends RecyclerView.ViewHolder {
public TextView messageBody;
public RecvdMessageHolder(View itemView) {
super(itemView);
messageBody = (TextView) itemView.findViewById(R.id.text_message_body);
}
}
My activity
public class MainActivity extends AppCompatActivity {
private EditText editText;
private RecyclerView mMessageRecycler;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter MessageListAdapter;
List<Messages> data;
//init client
Retrofit retrofit = RetrofitClient.getRetrofitClient();
//contact with the interface
APIService apiService = retrofit.create(APIService.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.my_msg);
data = new ArrayList<>();
mMessageRecycler = (RecyclerView) findViewById(R.id.reyclerview_message_list);
MessageListAdapter = new MessageListAdapter(data , this);
// messageListAdapter.notifyDataSetChanged();
mMessageRecycler.setAdapter(MessageListAdapter);
mMessageRecycler.setLayoutManager(new LinearLayoutManager(this));
mMessageRecycler.setHasFixedSize(true);
}
public void clickedbtn(View view) {
fetchMessages();
}
private void fetchMessages() {
Call<List<Messages>> res = apiService.getBotResponse(editText.getText().toString());
res.enqueue(new Callback<List<Messages>>() {
#Override
public void onResponse(Call<List<Messages>> call, Response<List<Messages>> response) {
List<Messages> messages = response.body();
data.addAll(messages);//Changed here
MessageListAdapter.notifyDataSetChanged();//Changed here
mMessageRecycler.smoothScrollToPosition(messages.size()-1);
}
#Override
public void onFailure(Call<List<Messages>> call, Throwable t) {
}
});
}
My model class
public class Messages {
#SerializedName("recipient_id")
#Expose
private String recipientId;
#SerializedName("text")
#Expose
private String text;
public Messages(String text) {
this.text = text;
}
public String getRecipientId() {
return recipientId;
}
public void setRecipientId(String recipientId) {
this.recipientId = recipientId;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
Try adding both the instantiation of the Adapter and the RecyclerView.setAdapter() to the retrofit onResponse():
Like this:
Call<List<Messages>> res = apiService.getBotResponse(editText.getText().toString());
res.enqueue(new Callback<List<Messages>>() {
#Override
public void onResponse(Call<List<Messages>> call, Response<List<Messages>> response) {
List<Messages> messages = response.body();
//Init the Adpater here!!
MessageListAdapter = new MessageListAdapter(data , this);
//SetAdapter here!!
mMessageRecycler.setAdapter(MessageListAdapter);
data.addAll(messages);//Changed here
MessageListAdapter.notifyDataSetChanged();//Changed here
mMessageRecycler.smoothScrollToPosition(messages.size()-1);
}
#Override
public void onFailure(Call<List<Messages>> call, Throwable t) {
}
});
EDIT:
In addition to the above, your clickedbtn() should look like this:
public void clickedbtn(View view) {
Messages msg = new Messages(editText.getText().toString());
msg.setRecipientId("default");
data.add(msg);
MessageListAdapter.notifyDataSetChanged();
fetchMessages();
}

Retrofit bad request and RecyclerView: No adapter attached; skipping layout

Hi I am not sure why exactly my recycler view is not displaying but I get the following error even after initializing it on onCreate method as mentioned by other SO users who faced the same problem:
E/RecyclerView: No adapter attached; skipping layout
Also maybe Retrofit is not able to get the data so onResponse is never called hence onFailure is called. I am using an online JSON API. Link:
https://reqres.in/api/users?page=1&per_page=3
ApiClient.java
public class ApiClient {
public static final String BASE_URL = "https://reqres.in/api/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient(){
if(retrofit == null){
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}}
DataResponse.java
public class DataResponse {
#SerializedName("page")
private int page;
#SerializedName("per_page")
private int per_page;
#SerializedName("total")
private int total;
#SerializedName("total_pages")
private int total_pages;
#SerializedName("data")
List<Data> data;
public int getPage() {
return page;
}
public int getPer_page() {
return per_page;
}
public int getTotal() {
return total;
}
public int getTotal_pages() {
return total_pages;
}
public List<Data> getData() {
return data;
}
}
class Data {
#SerializedName("id")
private int id;
#SerializedName("first_name")
private String first_name;
#SerializedName("last_name")
private String last_name;
#SerializedName("avatar")
private String avatar;
public int getId() {
return id;
}
public String getFirst_name() {
return first_name;
}
public String getLast_name() {
return last_name;
}
public String getAvatar() {
return avatar;
}
}
ApiInterface
public interface ApiInterface {
#GET("users")
Call<List<DataResponse>> getUsers(#Query("page") int page, #Query("per_page") int per_page);}
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private List<Data> dataList;
private Context context;
public RecyclerAdapter(List<Data> dataList, Context context){
this.dataList = dataList;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Data data = dataList.get(position);
holder.fullname.setText(data.getFirst_name() + ", " + data.getLast_name());
Glide.with(context).load(data.getAvatar()).into(holder.avatar);
}
#Override
public int getItemCount() {
return dataList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
ImageView avatar;
TextView fullname;
public MyViewHolder(View itemView) {
super(itemView);
avatar = (ImageView) itemView.findViewById(R.id.cardView_image);
fullname = (TextView) itemView.findViewById(R.id.cardView_location);
}
}
public void addData(List<Data> data){
for(Data d: data){
dataList.add(d);
}
}}
MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar progressBar;
private GridLayoutManager layoutManager;
private RecyclerAdapter adapter;
private ApiInterface apiInterface;
private int page_num = 1;
private int per_page = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = null;
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
layoutManager = new GridLayoutManager(this, 2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
Call<List<DataResponse>> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<List<DataResponse>>() {
#Override
public void onResponse(Call<List<DataResponse>> call, Response<List<DataResponse>> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().get(1).getData();
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<List<DataResponse>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
}}
Would highly appreciate any help, thank you.
You are making an array request, convert it to object request(your api endpoint is returning json object). Change the call like this
Call<DataResponse> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<DataResponse>() {
#Override
public void onResponse(Call<DataResponse> call, Response<DataResponse> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().getData();
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<DataResponse> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
and api interface should be like this
public interface ApiInterface {
#GET("users")
Call<DataResponse> getUsers(#Query("page") int page,
#Query("per_page") int per_page);
}
Its happen because you request is failed and you are not set adapter for recycler view change it
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;`
private ProgressBar progressBar;
private GridLayoutManager layoutManager;
private RecyclerAdapter adapter;
private ApiInterface apiInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = null;
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
layoutManager = new GridLayoutManager(this, 2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
Call<List<DataResponse>> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<List<DataResponse>>() {
#Override
public void onResponse(Call<List<DataResponse>> call, Response<List<DataResponse>> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().get(1).getData();
adapter.notifydatasetchanged()
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<List<DataResponse>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
}

Categories