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.





try initializing List<City> data to an empty array list.
– Jojo Narte
Jun 29 at 16:30


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



enter image description here





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.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift