I found two similar questions but none of them worked. I am using fragment and RecyclerViews. The console displays the error
E/RecyclerView: No adapter attached; skipping layout
https://i.stack.imgur.com/dxk8y.png Adapter
https://i.stack.imgur.com/0J2io.png Fragment
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.listkos, null);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
User user = entries.get(position);
holder.textViewTitle.setText(entries.get(position).getnmkos());
holder.textViewShortDesc.setText(entries.get(position).getHp());
}
#Override
public int getItemCount() {
return entries.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView textViewTitle, textViewShortDesc;
ImageView imageView;
public MyViewHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.tvnm);
textViewShortDesc = itemView.findViewById(R.id.tvhp);
}
}
}
this fragment
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_beranda, container, false);
database = FirebaseDatabase.getInstance().getReference("Users");
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
re = (RecyclerView) view.findViewById(R.id.recyle_buka);
rvLayoutManager = new LinearLayoutManager(getActivity());
re.setLayoutManager(rvLayoutManager);
loadEntries();
return view;
}
private void loadEntries(){
database.child("Users").child(firebaseUser.getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
entries= new ArrayList<>();
for (DataSnapshot noteDataSnapshot:dataSnapshot.getChildren()){
User user=noteDataSnapshot.getValue(User.class);
user.setKey(noteDataSnapshot.getKey());
entries.add(user);
}
rvAdapter = new RvAdapter(entries) ;// This is still empty, probably
re.setAdapter(rvAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.w("LogFragment", "loadLog:onCancelled", databaseError.toException());
}
});
}
}
still not working guys
/*It looks like your post is mostly code; please add some more detail */
You must be create a Linear Layout manager. You must be set adapter to the recyclerview.
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
re.setLayoutManager(linearLayoutManager);
YourAdapter yourAdapter = new YourAdapter(list);
re.setAdapter(yourAdapter);
E/RecyclerView: No adapter attached; skipping layout
It means you haven't attached the adapter to your RecyclerView. So, you need to initialized your RecyclerView with an empty adapter. Something like this:
re = (RecyclerView) view.findViewById(R.id.recyle_buka);
rvLayoutManager = new LinearLayoutManager(getActivity());
re.setLayoutManager(rvLayoutManager);
// initialize empty adapter
entries= new ArrayList<>();
rvAdapter = new RvAdapter(entries);
re.setAdapter(rvAdapter);
Then, whenever you need to reload and refresh the RecyclerView, you should not doing this:
private void loadEntries(){
...
entries= new ArrayList<>();
for (DataSnapshot noteDataSnapshot:dataSnapshot.getChildren()){
User user=noteDataSnapshot.getValue(User.class);
user.setKey(noteDataSnapshot.getKey());
entries.add(user);
}
// DON'T DO THIS!
rvAdapter = new RvAdapter(entries) ;
re.setAdapter(rvAdapter);
}
because it resetting your adapter with a new Adapter.
What you need is refreshing the list and notifying the adapter for data changes.
First, add the following method to your Adapter to reload the list:
public void swap(List<User> list) {
entries.clear();
entries.addAll(list);
notifyDataSetChanged();
}
Then add it to your loadEntries(). Something like this:
private void loadEntries() {
...
List<User> newEntries = new ArrayList<>();
for (DataSnapshot noteDataSnapshot:dataSnapshot.getChildren()){
User user=noteDataSnapshot.getValue(User.class);
user.setKey(noteDataSnapshot.getKey());
newEntries.add(user);
}
rvAdapter.swap(newEntries);
}
This happen because you didn't set layout manager to Recyclerview.
Refer below example.
Initialize recyclerview
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
Initialize your adapter class
mAdapter = new MoviesAdapter(movieList);
now set layout manager to recyleview
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
Related
I am making an app on android studio. I want to display items in a recycler view using grid layout manager. I am adding three element into the array through which I want to display the recycler view. But when I am running the app, the app is displaying only two items. I don't know what's happening. I have set the height of the recycler view as wrap content still getting this problem.
Here's my code:-
ModelClass.java:-
public class ModelClass {
private String recyc_show_note;
ModelClass(String recyc_show_note){
this.recyc_show_note = recyc_show_note;
}
public String getRecyc_show_note() {
return recyc_show_note;
}}
Adapter.java:-
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<ModelClass> recyc_cust_notes;
public Adapter (List<ModelClass>recyc_cust_notes){
this.recyc_cust_notes = recyc_cust_notes;
}
#NonNull
#Override
public Adapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull Adapter.ViewHolder holder, int position) {
String recyc_show_note = recyc_cust_notes.get(position).getRecyc_show_note();
holder.setData(recyc_show_note);
}
#Override
//returns list size
public int getItemCount() {
return recyc_cust_notes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView recycler_view_note;
public ViewHolder(#NonNull View itemView) {
super(itemView);
recycler_view_note = itemView.findViewById(R.id.recyc_show_note);
}
public void setData(String recyc_show_note) {
recycler_view_note.setText(recyc_show_note);
}
}
}
MainActivity.java:-
RecyclerView recyclerView;
List<ModelClass>recyc_cust_notes;
Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
SharedPreferences getSharedPreference = getSharedPreferences("My Notes", MODE_PRIVATE);
String note = getSharedPreference.getString("Note", null);
initData();
initRecyclerView();
}
private void initRecyclerView() {
recyclerView = findViewById(R.id.recycler_view);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getApplicationContext(),2);
gridLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
recyclerView.setLayoutManager(gridLayoutManager);
adapter = new Adapter(recyc_cust_notes);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void initData() {
recyc_cust_notes = new ArrayList<>();
SharedPreferences getSharedPreference = getSharedPreferences("My Notes", MODE_PRIVATE);
String note = getSharedPreference.getString("Note", null);
recyc_cust_notes.add(new ModelClass(note));
recyc_cust_notes.add(new ModelClass("note"));
recyc_cust_notes.add(new ModelClass("sai"));
}
Just do it on this way
recyclerView.setLayoutManager(new GridLayoutManager(this, number_of_cols));
In XML
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_Grid"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Java Code
int cols = 3; // length of cols
RecyclerView recyclerView = findViewById(R.id.rv_Grid);
recyclerView.setLayoutManager(new GridLayoutManager(this, cols));
adapter = new MyRecyclerViewAdapter(this, list);
recyclerView.setAdapter(adapter);
And Remove setOrientation.
It's because of your gridLayoutManager Orientation.
You have 2 choices to show all items:
Change orientation to VERTICAL
Change your recyclerView width to match-parent
This question already has answers here:
"No adapter attached; skipping layout" on a fragment
(1 answer)
E/RecyclerView: No adapter attached; skipping layout (Using FRAGMENTS)
(2 answers)
recyclerview No adapter attached; skipping layout
(38 answers)
Closed 2 years ago.
I am developing an app with fragments and recycler view with firebase database. I want the app to fetch data from database and display it in the fragment layout. I pretty much think that my code is fine and should work properly.
I get the error log E/RecyclerView: No adapter attached; skipping layout
I tried everything out there in other questions, forums.
This is my home.java code :
public class home extends Fragment {
private OnFragmentInteractionListener mListener;
public home() {
}
// TODO: Rename and change types and number of parameters
public static home newInstance() {
home fragment = new home();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
//to recycler view.
private RecyclerView recyclerView;
public View view;
private ArrayList<Model> listItem;
ViewAdapter Vadapter;
DatabaseReference dbRef;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_home, container,false);
recyclerView = view.findViewById(R.id.carDetailsContainer);
listItem = new ArrayList<Model>();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
dbRef = FirebaseDatabase.getInstance().getReference().child("Cars");
Vadapter = new ViewAdapter(getContext(),listItem);
recyclerView.setAdapter(Vadapter);
return inflater.inflate(R.layout.fragment_home, container, false);
}
#Override
public void onStart() {
super.onStart();
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren())
{
Model model = new Model(ds.child("Name").getValue().toString(),ds.child("Milege").getValue().toString(),ds.child("Fuel").getValue().toString(),ds.child("Transmission").getValue().toString(),ds.child("Rate").getValue().toString());
listItem.add(model);
}
Vadapter = new ViewAdapter(getContext(),listItem);
recyclerView.setAdapter(Vadapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
dbRef.addValueEventListener(valueEventListener);
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
my Adapter class:
public class ViewAdapter extends RecyclerView.Adapter<ViewAdapter.MyViewHolder> {
DatabaseReference ref;
FirebaseDatabase fbRref;
Context context;
ArrayList<Model> model;
public ViewAdapter(Context c, ArrayList<Model> listItems)
{
this.context = c;
this.model = listItems;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.car_details, parent, false);
fbRref = FirebaseDatabase.getInstance();
ref = fbRref.getReference();
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.carName.setText(model.get(position).getmCarName());
holder.seatingCapacity.setText(model.get(position).getmSeatingCapacity());
}
#Override
public int getItemCount() {
return model.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
public TextView carName,seatingCapacity;
public MyViewHolder(#NonNull View itemView)
{
super(itemView);
carName = itemView.findViewById(R.id.car_name);
seatingCapacity = itemView.findViewById(R.id.seating_capacity);
}
}
}
I am stuck very badly at this.
Thanks in advance.
Try Changing
return inflater.inflate(R.layout.fragment_home, container, false);
to
return view;
You should move the initialization of your RecylcerView in onViewCreated instead of onCreateView, look at this answer
I have "E/RecyclerView: No adapter attached; skipping layout" error message.
I have recycleView inside fragment so I must have done something wrong on fragment1.java.
here is the code. I set adapter on the code as you can see, but I am getting this error. Any help would be appreciated. Thank you.
public class Fragment1 extends Fragment {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private ArrayList<Bible> arrayList;
private FirebaseDatabase database;
private DatabaseReference databaseReference;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment1, container, false);
recyclerView = rootView.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
//GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
arrayList = new ArrayList<>();
database = FirebaseDatabase.getInstance();
databaseReference = database.getReference("Bible");
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
arrayList.clear();
for(DataSnapshot snapshot: dataSnapshot.getChildren()){
Bible bible = snapshot.getValue(Bible.class);
arrayList.add(bible);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.e("fragment1", String.valueOf(databaseError.toException()));//에러문 출력
}
});
adapter = new BibleAdapter(arrayList, getContext());
recyclerView.setAdapter(adapter);
return rootView;
}
}
public class BibleAdapter extends RecyclerView.Adapter {
private ArrayList<Bible> arrayList;
private Context context;
private OnVerseItemClickListener listener;
public BibleAdapter(ArrayList<Bible> arrayList, Context context) {
this.arrayList = arrayList;
this.context = context;
}
public void setOnItemClickListener(OnVerseItemClickListener listener){
this.listener = listener;
}
#NonNull
#Override
public BibleAdapter.BibleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.verse_item, parent, false);
BibleViewHolder holder = new BibleViewHolder(view, listener);
return holder;
}
#Override
public void onBindViewHolder(#NonNull BibleAdapter.BibleViewHolder holder, int position) {
Glide.with(holder.imageView)
.load(arrayList.get(position).getImage())
.into(holder.imageView);
holder.bibleType.setText(arrayList.get(position).getBibleType());
holder.keysentance.setText(arrayList.get(position).getKeysentance());
holder.verse.setText(arrayList.get(position).getVerse());
}
#Override
public int getItemCount() {
return (arrayList!=null? arrayList.size():0);
}
public class BibleViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView bibleType;
TextView verse;
TextView keysentance;
public BibleViewHolder(#NonNull View itemView, final OnVerseItemClickListener listener) {
super(itemView);
this.imageView = itemView.findViewById(R.id.imageView);
this.bibleType = itemView.findViewById(R.id.bibleType);
this.keysentance = itemView.findViewById(R.id.keysentance);
this.verse = itemView.findViewById(R.id.verse);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
if(listener != null){
listener.onItemClick(BibleViewHolder.this, v, position);
}
}
});
}
}
}
in your code you have create adapter with empty arrayList, but never after that you update the list.
in adapter create swapData() method and call it when you have to refresh data or have refreshed data, in your case you will get it in onDataChange().
And also define adapter before adding listener:
adapter = new BibleAdapter(arrayList, getContext());
recyclerView.setAdapter(adapter);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
arrayList.clear();
for(DataSnapshot snapshot: dataSnapshot.getChildren()){
Bible bible = snapshot.getValue(Bible.class);
arrayList.add(bible);
}
adapter.swapData(arrayList);
//adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.e("fragment1", String.valueOf(databaseError.toException()));//에러문 출력
}
});
in adapter class create method as:
public void swapData(ArrayList<Bible> filtersList) {
if (filtersList != null) {
this.arrayList.clear();
this.arrayList.addAll(filtersList);
notifyDataSetChanged();
}
}
I have implemented the android master/detail flow template in android. I have changed it so that it loads the data from database on first load. The list populates fine.
I have a refresh button which calls an asyncTask with a callback, which effectively updates the data using http and updates the database. I now need to update the data in the list. I have tried several approaches to update the recyclerView but it just wont update. Any ideas.
public void refreshWeatherCharts() {
WeatherChartFetchData callbackservice = new WeatherChartFetchData(this) {
#Override
public void receiveData(boolean success) {
if (success)
WeatherChartListBuilder.loadData();
// RecyclerView.Adapter adapter = ((RecyclerView) recyclerView).getAdapter();
RecyclerView rc = (RecyclerView) recyclerView;
rc.invalidate();
}
};
callbackservice.execute(null, null, null);
}
private void setupRecyclerView(#NonNull RecyclerView recyclerView) {
recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(WeatherChartListBuilder.ITEMS));
}
/////////
public class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final List<WeatherChart> mValues;
public SimpleItemRecyclerViewAdapter(List<WeatherChart> items) {
mValues = items;
}
public void updateData(ArrayList<WeatherChart> viewModels) {
mValues.clear();
mValues.addAll(viewModels);
notifyDataSetChanged();
}
public void addItem(int position, WeatherChart viewModel) {
mValues.add(position, viewModel);
notifyItemInserted(position);
}
public void removeItem(int position) {
mValues.remove(position);
notifyItemRemoved(position);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.weatherchart_list_content, parent, false);
return new ViewHolder(view);
}
Managed to sort it. I refactored the recyclerView to the following:
recyclerView = (RecyclerView) findViewById(R.id.weatherchart_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new SimpleItemRecyclerViewAdapter(ITEMS);
// new SimpleItemRecyclerViewAdapter(ITEMS);
//SimpleItemRecyclerViewAdapter.ViewHolde
recyclerView.setAdapter(mAdapter);
You don't need to create a new adapter each time some item's value changes in your data set or if you added new items to your data set, or removed items, or even if the whole list has changed. Just update the data set in your adapter which in your case is a List of WeatherCharts.
public void refreshWeatherCharts() {
WeatherChartFetchData callbackservice = new WeatherChartFetchData(this) {
#Override
public void receiveData(boolean success) {
if (success) {
WeatherChartListBuilder.loadData();
RecyclerView.Adapter adapter = ((RecyclerView) recyclerView).getAdapter();
((SimpleItemRecyclerViewAdapter) adapter).updateData(WeatherChartListBuilder.ITEMS);
}
}
};
callbackservice.execute(null, null, null);
}
viewAdapter = recyclerView.getAdapter();
viewAdapter.notifyDataSetChanged();
I am trying to use recyclerview and setting up adapter but I am getting error :-
No adapter attached; skipping layout
So please help me how to solve this problem
public class FragmentTwo extends Fragment {
private AppAdapter mAppAdapter;
private ArrayList<Model> mModel;
#Bind(R.id.recycler_view)
RecyclerView recyclerView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_two, container, false);
ButterKnife.bind(this, v);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(mAppAdapter);
parseData();
return v;
}
private void parseData() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.addConverterFactory(GsonConverterFactory.create())
.build();
ReqInterface reqInterface = retrofit.create(ReqInterface.class);
Call<Model> call = reqInterface.getAdvanceData("france");
call.enqueue(new Callback<Model>() {
#Override
public void onResponse(Call<Model> call, Response<Model> response) {
Model model = response.body();
mModel = new ArrayList<Model>(Arrays.asList(model));
mAppAdapter = new AppAdapter(mModel);
recyclerView.setAdapter(mAppAdapter);
mAppAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<Model> call, Throwable t) {
}
});
}
}
Here is my Recyclerview Adapter class:-
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
private ArrayList<Model> mModel;
TextView highTemp;
public AppAdapter(ArrayList<Model> model) {
mModel = model;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView highTemp;
public ViewHolder(View view) {
super(view);
highTemp = (TextView) view.findViewById(R.id.card_view_tv_hightemp);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.fragment_two, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.highTemp.setText(String.valueOf(mModel.getName);
}
#Override
public int getItemCount() {
return mModel.size();
}
}
Thanks in advance
You never initialize the adapter mAppAdapter so it's null at runtime. You're missing something like mAppAdapter = new AppAdapter(yourdata);
before the call to setAdapter.
Your adapter mAppAdapter is never initialised i.e. it is null.
Therefore recyclerView.setAdapter(mAppAdapter); is the same as recyclerView.setAdapter(null); so you aren't actually ever setting an adapter!
Remember to initialise your fields:
mAppAdapter = new AppAdapter(mModel); // or whatever constructor you want
recyclerView.setAdapter(mAppAdapter);
Change
recyclerView.setAdapter(mAppAdapter);
to
recyclerView.setAdapter(new AppAdapter(model));
You never create your mAppAdapter.
To solve this, create a new instance of your adapter and pass that in the parameters of .setAdapter.
In other words, you should use .setAdapter(new AppAdapter(...)) where ... is replaced with the parameters that you have created in AppAdapter.
I usually do the retrofit call in an asynctask, then when you get the response from the server, you create a new adapter and set it to the recyclerview.
Anyway, try removing the .setAdapter line from the onCreate() method and just leave it as you have it.
It works and it doesn't crash, the reason it crashes it's because the adapter is null (it has no elements).
I hope it helps!