1

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.

3 Answers3

0

First of all your adapter xml root LinearLayout has height set to match_parent so change that to wrap_content.

Second one override onViewCreated and there set recyclerView not in onCreateView. For example:

 @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);

Yupi
  • 4,402
  • 3
  • 18
  • 37
0

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.

    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

    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");
Khaled Lela
  • 7,831
  • 6
  • 45
  • 73
  • 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 '18 at 17:31
  • @TheWarInMyMind Checkout my updated [answer](https://stackoverflow.com/a/51110928/1283715) – Khaled Lela Jun 30 '18 at 01:06
0
  • I have create a simple app to simulate your case.
  • RecyclerView width must be 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

Khaled Lela
  • 7,831
  • 6
  • 45
  • 73
  • 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 '18 at 10:04
  • What about `RecyclerView` width still `wrap_content` or you changed as `match_parent`? – Khaled Lela Jun 30 '18 at 13:40