Items in RecyclerView in a Fragmnet don't appear
Items in RecyclerView in a Fragmnet don't appear
I saw there are similar post but my code is the same as the codes in the solutions so they weren't useful in my case. My app starts but and two tabs are shown. However the one that is supposed to show the items from a RecyclerView that's in it is empty.I also get this error:
E/RecyclerView: No adapter attached; skipping layout
So I have an Activity with a TabLayout and a ViewPager
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
PagerAdapter pagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout=findViewById(R.id.tab_layout);
viewPager=findViewById(R.id.view_pager);
tabLayout.addTab(tabLayout.newTab().setText("CitiesFragment"));
tabLayout.addTab(tabLayout.newTab().setText("My CitiesFragment"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
pagerAdapter=new PagerAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
This is a fragment with only a RecyclerView in it
public class CitiesFragment extends Fragment {
RecyclerView recyclerView;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View itemView = inflater.inflate(R.layout.cities_layout, container, false);
recyclerView = itemView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
List<City> data = Database.getDatabase();
CitiesAdapter adapter = new CitiesAdapter(data);
recyclerView.setAdapter(adapter);
return itemView;
}
}
This is the XML for the fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
And this is the Adapter
public class CitiesAdapter extends RecyclerView.Adapter<CitiesVIewHolder> {
List<City> data;
private int itemCount;
public CitiesAdapter(List<City> data) {
this.data = data;
itemCount=data.size();
}
@NonNull
@Override
public CitiesVIewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.city_layout, viewGroup, false);
CitiesVIewHolder viewHolder = new CitiesVIewHolder(itemView);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull CitiesVIewHolder citiesVIewHolder, int position) {
City city = data.get(position);
citiesVIewHolder.txtCityName.setText(city.getCityName());
citiesVIewHolder.txtCityInfo.setText(city.getCityInfo());
LoadImageTask loadImageTask = new LoadImageTask(citiesVIewHolder.imgCity);
loadImageTask.execute(city.getImageUrl());
}
@Override
public int getItemCount() {
return itemCount;
}
}
And the XML for the Adapter
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/img_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txt_city_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txt_city_info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
My PagerAdapter only returns one of the two fragments(one of them is currently empty and the other on is with the RecyclerView)
public class PagerAdapter extends FragmentStatePagerAdapter {
private int itemCount;
public PagerAdapter(FragmentManager fm, int itemCount) {
super(fm);
this.itemCount = itemCount;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new CitiesFragment();
case 1:
return new MyCitiesFragment();
default:
return null;
}
}
@Override
public int getCount() {
return itemCount;
}
}
I am sorry for the code overload but I really can not understand what I'm doing wrong. Thanks for the help in advance.
List<City> data
Load datasource on background then notify adapter when finished.
– Khaled Lela
Jun 29 at 16:33
set your recycler view height to match parent and try. also check the city data size in your adapter.
– pop
Jun 29 at 16:49
@pop
RecyclerView
will not has an issue with height= wrap-content
, as it's parent LinearLayout height=match_parent
.– Khaled Lela
Jun 29 at 16:59
RecyclerView
height= wrap-content
LinearLayout height=match_parent
what about data size??
– pop
Jun 29 at 17:01
3 Answers
3
First of all your adapter xml
root LinearLayout
has height set to match_parent
so change that to wrap_content
.
xml
LinearLayout
match_parent
wrap_content
Second one override onViewCreated
and there set recyclerView
not in onCreateView
. For example:
override onViewCreated
recyclerView
onCreateView
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setHasFixedSize(true);
List<City> data = Database.getDatabase();
CitiesAdapter adapter = new CitiesAdapter(data);
recyclerView.setAdapter(adapter);
}
Also consider adding line: recyclerView.setHasFixedSize(true);
recyclerView.setHasFixedSize(true);
nothing chenges.I still get the error and an empty fragment
– TheWarInMyMind
Jun 29 at 17:26
Than check
data
is it empty. Log
it by checking data.size()
– Yupi
Jun 29 at 17:33
data
Log
data.size()
It shows the correct number of items. The problem must be something with the loading of the layout
– TheWarInMyMind
Jun 29 at 17:37
I think you are missing the line:
tabLayout.setupWithViewPager(viewPager);
in MainActivity
as well. Add it below line where you set adapter to viewPager
– Yupi
Jun 29 at 17:57
tabLayout.setupWithViewPager(viewPager);
MainActivity
viewPager
if I add something like a TextView to the ViewPager it shows up. So the RecyclerView is the part that's not working.
– TheWarInMyMind
Jun 29 at 18:01
E/RecyclerView: No adapter attached; skipping layout
TabLayout
display fragment with recyclerView but fragment takes more time to load datasource that makes recycler created without adapter attached.
TabLayout
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View itemView = inflater.inflate(R.layout.cities_layout, container, false);
recyclerView = itemView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// List<City> data = Database.getDatabase(); // Don't fetch data on Main (UI) Thread
CitiesAdapter adapter = new CitiesAdapter(new ArrayList<City>()); //
recyclerView.setAdapter(adapter);
// Display city here one background and then update adapter.
return itemView;
}
If Datasource fetch data from local database then you can just use handler
or postDelay
on RecyclerView
handler
postDelay
RecyclerView
recyclerView.postDelay(new Runnable(){
public void run(){
adapter.setCityList(result);
}
},500);
If you load data for server datasource the use background task, You can check this answer for fetch data from server with smooth way.
// load datasource inside Async Task.
new AsyncTaskHandler(new OnFinishCallback() {
@Override
public void onSuccess(List<City> result) {
adapter.setCityList(result);
}
}).execute("param that need to load datasource");
the data consist of simply adding the names of the cities, 2 sentences of info and an image.The info is taken from another class,only the images are from the Internet. I have an AsyncTask class for the image loading.I even tried to put only 2 items in the RecyclerView and your suggestion with postDelayed but nothing changes
– TheWarInMyMind
Jun 29 at 17:31
@TheWarInMyMind Checkout my updated answer
– Khaled Lela
Jun 30 at 1:06
RecyclerView
width must be match_partent
RecyclerView
match_partent
<!--RecyclerView width must be match_parent-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
You can find the complete sample/CityPreview app on Github
I just deleted the CitiesAdapter class and rewrote it the same as it was and for some reson that fixed it. Similar things have hapened to me a few times already. I don't understand why Android Studio somethimes bugs like that. However, thanks for trying and sorry for wasting your time.
– TheWarInMyMind
Jun 30 at 10:04
What about
RecyclerView
width still wrap_content
or you changed as match_parent
?– Khaled Lela
Jun 30 at 13:40
RecyclerView
wrap_content
match_parent
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
try initializing
List<City> data
to an empty array list.– Jojo Narte
Jun 29 at 16:30