Just implemented RecyclerView
in my code, replacing ListView
.
Everything works fine. The data is displayed.
But error messages are being logged:
15:25:53.476 E/RecyclerView: No adapter attached; skipping layout
15:25:53.655 E/RecyclerView: No adapter attached; skipping layout
for the following code:
ArtistArrayAdapter adapter = new ArtistArrayAdapter(this, artists);
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
As you can see I have attached an adapter for RecyclerView
.
So why do I keep getting this error?
I have read other questions related to the same problem but none of them help.
This question is related to
android
android-recyclerview
It worked for me.
android:usesCleartextTraffic="true"
android.support.v7.widget.CardView
Replace cardview xml design with android x. Must be such;
androidx.cardview.widget.CardView
android.support.v7.widget.RecyclerView
Replace cardview xml design with android x. Must be such;
androidx.recyclerview.widget.RecyclerView
In my situation it was a forgotten component which locates in ViewHolder class but it wasn't located in layout file
Just put code inside onCreate() method
/* Like This*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(YourActivity.this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
mAdapter = new YourAdapter(YourModelClassObject);
recyclerView.setAdapter(mAdapter);
}
1) Create ViewHolder that does nothing :)
// SampleHolder.java
public class SampleHolder extends RecyclerView.ViewHolder {
public SampleHolder(View itemView) {
super(itemView);
}
}
2) Again create RecyclerView that does nothing :)
// SampleRecycler.java
public class SampleRecycler extends RecyclerView.Adapter<SampleHolder> {
@Override
public SampleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(SampleHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
}
3) Now when your real recycler is not ready just use the sample one like below.
RecyclerView myRecycler = (RecyclerView) findViewById(R.id.recycler_id);
myRecycler.setLayoutManager(new LinearLayoutManager(this));
myRecycler.setAdapter(new SampleRecycler());
This is not best solution though but it works! Hope this is helpful.
I had the same problem and realized I was setting both the LayoutManager and adapter after retrieving the data from my source instead of setting the two in the onCreate method.
salesAdapter = new SalesAdapter(this,ordersList);
salesView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
salesView.setAdapter(salesAdapter);
Then notified the adapter on data change
//get the Orders
Orders orders;
JSONArray ordersArray = jObj.getJSONArray("orders");
for (int i = 0; i < ordersArray.length() ; i++) {
JSONObject orderItem = ordersArray.getJSONObject(i);
//populate the Order model
orders = new Orders(
orderItem.getString("order_id"),
orderItem.getString("customer"),
orderItem.getString("date_added"),
orderItem.getString("total"));
ordersList.add(i,orders);
salesAdapter.notifyDataSetChanged();
}
Solved by setting the initialized empty list and adapter at the bottom and calling notifyDataSetChanged when results are fetched.
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerviewItems.setLayoutManager(linearLayoutManager);
someAdapter = new SomeAdapter(getContext(),feedList);
recyclerviewItems.setAdapter(someAdapter);
In my case it happened cause i embedded a RecyclerView in a LinearLayout.
I previously had a layout file only containing one root RecyclerView as follows
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/fragment_products"
android:name="Products.ProductsFragment"
app:layoutManager="LinearLayoutManager"
tools:context=".Products.ProductsFragment"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"/>
I believe the problem is within the 3 lines separated. Anyway, I think its a simple problem, ill be working on it tomorrow; thought i should write what i found before forgetting about this thread.
This happens because the actual inflated layout is different from that which is being referred by you while finding the recyclerView. By default when you create the fragment, the onCreateView method appears as follows:
return inflater.inflate(R.layout.<related layout>,container.false);
Instead of that, separately create the view and use that to refer to recyclerView
View view= inflater.inflate(R.layout.<related layout>,container.false);
recyclerview=view.findViewById(R.id.<recyclerView ID>);
return view;
// It happens when you are not setting the adapter during the creation phase: call notifyDataSetChanged() when api response is getting Its Working
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
magazineAdapter = new MagazineAdapter(getContext(), null, this );
newClipRecyclerView.setAdapter(magazineAdapter);
magazineAdapter.notifyDataSetChanged();
APICall();
}
public void APICall() {
if(Response.isSuccessfull()){
mRecyclerView.setAdapter(mAdapter);
}
}
Just move setting the adapter into onCreate with an empty data and when you have the data call:
mAdapter.notifyDataSetChanged();
I have the same situation with you, display is ok, but error appear in the locat. That's my solution: (1) Initialize the RecyclerView & bind adapter ON CREATE()
RecyclerView mRecycler = (RecyclerView) this.findViewById(R.id.yourid);
mRecycler.setAdapter(adapter);
(2) call notifyDataStateChanged when you get the data
adapter.notifyDataStateChanged();
In the recyclerView's source code, there is other thread to check the state of data.
public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mObserver = new RecyclerView.RecyclerViewDataObserver(null);
this.mRecycler = new RecyclerView.Recycler();
this.mUpdateChildViewsRunnable = new Runnable() {
public void run() {
if(RecyclerView.this.mFirstLayoutComplete) {
if(RecyclerView.this.mDataSetHasChangedAfterLayout) {
TraceCompat.beginSection("RV FullInvalidate");
RecyclerView.this.dispatchLayout();
TraceCompat.endSection();
} else if(RecyclerView.this.mAdapterHelper.hasPendingUpdates()) {
TraceCompat.beginSection("RV PartialInvalidate");
RecyclerView.this.eatRequestLayout();
RecyclerView.this.mAdapterHelper.preProcess();
if(!RecyclerView.this.mLayoutRequestEaten) {
RecyclerView.this.rebindUpdatedViewHolders();
}
RecyclerView.this.resumeRequestLayout(true);
TraceCompat.endSection();
}
}
}
};
In the dispatchLayout(), we can find there is the error in it:
void dispatchLayout() {
if(this.mAdapter == null) {
Log.e("RecyclerView", "No adapter attached; skipping layout");
} else if(this.mLayout == null) {
Log.e("RecyclerView", "No layout manager attached; skipping layout");
} else {
i have this problem , a few time problem is recycleView put in ScrollView object
After checking implementation, the reason appears to be the following. If RecyclerView gets put into a ScrollView, then during measure step its height is unspecified (because ScrollView allows any height) and, as a result, gets equal to minimum height (as per implementation) which is apparently zero.
You have couple of options for fixing this:
(Can be followed for android.support.v4.widget.NestedScrollView
as well)
These Lines must be in OnCreate
:
mmAdapter = new Adapter(msgList);
mrecyclerView.setAdapter(mmAdapter);
I was getting the same two error messages until I fixed two things in my code:
(1) By default, when you implement methods in the RecyclerView.Adapter
it generates:
@Override
public int getItemCount() {
return 0;
}
Make sure you update your code so it says:
@Override
public int getItemCount() {
return artists.size();
}
Obviously if you have zero items in your items then you will get zero things displayed on the screen.
(2) I was not doing this as shown in the top answer: CardView layout_width="match_parent" does not match parent RecyclerView width
//correct
LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_listitem, parent, false);
//incorrect (what I had)
LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_listitem,null);
(3) EDIT: BONUS:
Also make sure you set up your RecyclerView
like this:
<android.support.v7.widget.RecyclerView
android:id="@+id/RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
NOT like this:
<view
android:id="@+id/RecyclerView"
class="android.support.v7.widget.RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I have seen some tutorials using the latter method. While it works I think it generates this error too.
Just add the following to RecyclerView
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
Example:
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</android.support.v7.widget.RecyclerView>
Make sure you set the layout manager for your RecyclerView by:
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
Instead of LinearLayoutManager
, you can use other layout managers too.
First initialize the adapter
public void initializeComments(){
comments = new ArrayList<>();
comments_myRecyclerView = (RecyclerView) findViewById(R.id.comments_recycler);
comments_mLayoutManager = new LinearLayoutManager(myContext);
comments_myRecyclerView.setLayoutManager(comments_mLayoutManager);
updateComments();
getCommentsData();
}
public void updateComments(){
comments_mAdapter = new CommentsAdapter(comments, myContext);
comments_myRecyclerView.setAdapter(comments_mAdapter);
}
When ever there is a change in the dataset set, just call the updateComments method.
In Kotlin we had this weird illogical issue.
This didn't work:
mBinding.serviceProviderCertificates.apply {
adapter = adapter
layoutManager = LinearLayoutManager(activity)
}
While this worked:
mBinding.serviceProviderCertificates.adapter = adapter
mBinding.serviceProviderCertificates.layoutManager = LinearLayoutManager(activity)
Once I get more after work hours, I will share more insights.
In your RecyclerView
adapter class, for example MyRecyclerViewAdapter
, make a constructor with the following params.
MyRecyclerViewAdapter(Context context, List<String> data) {
this.mInflater = LayoutInflater.from(context); // <-- This is the line most people include me miss
this.mData = data;
}
mData
is the data that you'll pass to the adapter. It is optional if you have no data to be passed.
mInflater
is the LayoutInflater
object that you have created and you use in the OnCreateViewHolder
function of the adapter.
After this, you attach the adapter in the MainActivity or wherever you want to on the main/UI thread properly like
MyRecyclerViewAdapter recyclerAdapter;
OurDataStuff mData;
....
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Like this:
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerAdapter = new RecyclerAdapter(this, mData); //this, is the context. mData is the data you want to pass if you have any
recyclerView.setAdapter(recyclerAdapter);
}
....
Check if you have missed to call this method in your adapter
@Override
public int getItemCount() {
return list.size();
}
I had the same error I fixed it doing this if you are waiting for data like me using retrofit or something like that
Put before Oncreate
private ArtistArrayAdapter adapter;
private RecyclerView recyclerView;
Put them in your Oncreate
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new ArtistArrayAdapter( artists , R.layout.list_item ,getApplicationContext());
recyclerView.setAdapter(adapter);
When you receive data put
adapter = new ArtistArrayAdapter( artists , R.layout.list_item ,getApplicationContext());
recyclerView.setAdapter(adapter);
Now go in your ArtistArrayAdapter class and do this what it will do is if your array is empty or is null it will make GetItemCount return 0 if not it will make it the size of artists array
@Override
public int getItemCount() {
int a ;
if(artists != null && !artists.isEmpty()) {
a = artists.size();
}
else {
a = 0;
}
return a;
}
My problem was my recycler view looked like this
<android.support.v7.widget.RecyclerView
android:id="@+id/chatview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</android.support.v7.widget.RecyclerView>
When it should have looked like this
<android.support.v7.widget.RecyclerView
android:id="@+id/chatview"
android:layout_width="395dp"
android:layout_height="525dp"
android:layout_marginTop="52dp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp"></android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
In my case, I was setting the adapter inside onLocationChanged()
callback AND debugging in the emulator. Since it didn't detected a location change it never fired. When I set them manually in the Extended controls of the emulator it worked as expected.
I had this error, and I tried to fix for a while until I found the solution.
I made a private method buildRecyclerView, and I called it twice, first on onCreateView and then after my callback (in which I fetch data from an API). This is my method buildRecyclerView in my Fragment:
private void buildRecyclerView(View v) {
mRecyclerView = v.findViewById(R.id.recycler_view_loan);
mLayoutManager = new LinearLayoutManager(getActivity());
((LinearLayoutManager) mLayoutManager).setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new LoanAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
Besides, I have to modify the method get-Item-Count in my adapter, because On on-Create-View the list is null and it through an error. So, my get-Item-Count is the following:
@Override
public int getItemCount() {
try {
return mLoanList.size();
} catch (Exception ex){return 0;}
}
ArtistArrayAdapter adapter = new ArtistArrayAdapter(this, artists);
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
Just replace above code with this and it should work. What you did wrong is you called setAdapter(adapter) before calling layout manager.
Adding yet another answer since I came across this thread googling the error. I was trying to initialize a PreferenceFragmentCompat
but I forgot to inflate the preference XML in onCreatePreferences
like this:
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.fragment_settings, null)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
// Missing this line here:
// setPreferencesFromResource(R.xml.settings, rootKey)
}
}
The error was a mystery until I realized that PreferenceFragmentCompat
must be using a RecyclerView
internally.
This is really a simple error you are getting, there in no need of doing any codes in this. This error occurs due to the wrong layout file used by the activity. By IDE i automatically created a layout v21 of a layout which became a default layout of the activity. all codes I did in the old layout file and new one was only having few xml codes, which led to that error.
Solution: Copy all codes of old layout and paste in layout v 21
This issue is because you are not adding any LayoutManager
for your RecyclerView
.
Another reason is because you are calling this code in a NonUIThread. Make sure to call this call in the UIThread.
The solution is only you have to add a LayoutManager
for the RecyclerView
before you setAdapter
in the UI Thread.
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
I was getting same issue, I did every thing correct excepted in xml file:
step first 1: initialize recyclerview & List & Adaptor:
RecyclerView recyclerview;
List<ModelName> list;
ProvideBidAdaptor adaptor;
step 2: bind it in onCreate-
recyclerview = findByViewId(R.id.providerBidRV);
recyclerview.setLayoutManager(new LinearLayoutManager(this));
recyclerview.setHasFixedSize(true);
list = new ArrayList<>();
step 3: Where you getting response or list - add list- (i am getting from response)>
responseList.addAll(response.getResponse());
adaptor = new ProvideBidAdaptor(this, responseList);
binding.detailsRV.setAdapter(adaptor);
Here is my xml file where i implement RecyclerView
:
I was forget orientation in LinearLayout
, after this correction- RecyclerView
attached.
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.Bidding.ProvideBid">
<include
android:id="@+id/toolbar"
layout="@layout/app_toolbar"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/providerBidRV"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</layout>
Here is Adaptor:
public class ProvideBidAdaptor extends RecyclerView.Adapter<ProvideBidAdaptor.ViewHolder> {
Context context;
List<Response> responseList;
DateTime dateTimeInstance = new DateTime();
public ProvideBidAdaptor(Context context, List<Response> responseList) {
this.context = context;
this.responseList = responseList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.geo_presence_item_list, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final Response detailsResponse = responseList.get(position);
if (!detailsResponse.getUserId().isEmpty()) {
holder.day.setText(detailsResponse.getDay());
holder.locationType.setText(detailsResponse.getLocationType());
}
}
@Override
public int getItemCount() {
return responseList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView date,locationType;
CardView provideBidCV;
LinearLayout dayLLayout,locationTypeLLayout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
date = itemView.findViewById(R.id.date_value);
day = itemView.findViewById(R.id.day_value);
locationType = itemView.findViewById(R.id.locationType_value);
locationTypeLLayout = itemView.findViewById(R.id.locationTypeLLayout);
}
}
}
It happens when you are not setting the adapter during the creation phase:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
....
}
public void onResume() {
super.onResume();
mRecyclerView.setAdapter(mAdapter);
....
}
Just move setting the adapter into onCreate with an empty data and when you have the data call:
mAdapter.notifyDataSetChanged();
I lost 16 minutes of my life with this issue, so I'll just admit to this incredibly embarrassing mistake that I was making- I'm using Butterknife and I bind the view in onCreateView in this fragment.
It took a long time to figure out why I had no layoutmanager - but obviously the views are injected so they won't actually be null, so the the recycler will never be null .. whoops!
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Override
public View onCreateView(......) {
View v = ...;
ButterKnife.bind(this, v);
setUpRecycler()
}
public void setUpRecycler(Data data)
if (recyclerView == null) {
/*very silly because this will never happen*/
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
//more setup
//...
}
recyclerView.setAdapter(new XAdapter(data));
}
If you are getting an issue like this trace your view and use something like uiautomatorviewer
I have solved this error. You just need to add layout manager and add the empty adapter.
Like this code:
myRecyclerView.setLayoutManager(...//your layout manager);
myRecyclerView.setAdapter(new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
});
//other code's
// and for change you can use if(mrecyclerview.getadapter != speacialadapter){
//replice your adapter
//}
For those who use the RecyclerView
within a fragment and inflate it from other views: when inflating the whole fragment view, make sure that you bind the RecyclerView
to its root view.
I was connecting and doing everything for the adapter correctly, but I never did the binding. This answer by @Prateek Agarwal has it all for me, but here is more elaboration.
Kotlin
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val rootView = inflater?.inflate(R.layout.fragment_layout, container, false)
recyclerView = rootView?.findViewById(R.id.recycler_view_id)
// rest of my stuff
recyclerView?.setHasFixedSize(true)
recyclerView?.layoutManager = viewManager
recyclerView?.adapter = viewAdapter
// return the root view
return rootView
}
Java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView= inflater.inflate(R.layout.fragment_layout,container,false);
recyclerview= rootView.findViewById(R.id.recycler_view_id);
return rootView;
}
Source: Stackoverflow.com