RecyclerView in Fragment : No adapter attached skipping layout

荒凉一梦 提交于 2020-01-30 12:06:47

问题


I'm trying to use RecyclerView in Fragment, but I'm facing a problem, my list doesn't appear and I have this error:

E/RecyclerView: No adapter attached; skipping layout

I checked the solutions, apparently the problems appeared when:

  • RecyclerView initialized after Adapter

  • Bind and set recyclerView in onCreateView instead of onViewCreated

But I gave attention, I tried alternatives and I'm still facing the same issue.

Here is my code of the fragment:

import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.gosia.weightapplication.databinding.FragmentHistoryBinding;
import com.example.gosia.weightapplication.model.WeightData;
import com.orhanobut.logger.Logger;
import com.raizlabs.android.dbflow.sql.language.SQLite;

import java.util.ArrayList;
import java.util.List;


public class HistoryFragment extends Fragment {

    private List<WeightData> mWeightData = new ArrayList<>();
    private FragmentHistoryBinding mFragmentHistoryBinding;
    private ListAdapter mAdapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_history, viewGroup, false);

        //binding variable
        mFragmentHistoryBinding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_history);
        mFragmentHistoryBinding.setVariable(this);

        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //recycler
        RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        // define an adapter
        mAdapter = new ListAdapter(mWeightData, getContext());
        recyclerView.setAdapter(mAdapter);

        prepareWeightData();
    }

    private void prepareWeightData() {
        mWeightData = SQLite.select().
                from(WeightData.class).queryList();

        Logger.d(mWeightData.toString()); //The list isn't null, I have data to show

        mAdapter.notifyDataSetChanged();
    }
}

The XML:

    <?xml version="1.0" encoding="utf-8"?>

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View" />

        <variable
            name="variable"
            type="com.example.gosia.weightapplication.HistoryFragment" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorWhite"
        android:orientation="vertical">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:scrollbars="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <View
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/colorBlack">
            </View>

    </LinearLayout>
</layout>

Code of the ListAdapter:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import com.example.gosia.weightapplication.model.WeightData;

import java.util.List;

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

    private List<WeightData> mList;
    private Context mContext;
    private final LayoutInflater mLayoutInflater;

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView date, weight;
        public ImageView image;

        public ViewHolder(View v) {
            super(v);
            date = v.findViewById(R.id.text_view_date);
            weight = v.findViewById(R.id.text_view_weight);
            image = v.findViewById(R.id.image);
        }
    }

    public ListAdapter(List<WeightData> plist, Context pContext) {
        this.mList = plist;
        this.mContext = pContext;
        this.mLayoutInflater = LayoutInflater.from(this.mContext);
    }

    @Override
    public ListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = this.mLayoutInflater.inflate(R.layout.item_weight_history, parent, false);

        ViewHolder vh = new ViewHolder(v);

        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        //set data
        WeightData weightData = mList.get(position);
        holder.date.setText(weightData.getLastDayWeightMeasurement());
        holder.weight.setText(weightData.getWeight());

    }

    @Override
    public int getItemCount() {
        return mList.size();
    }
}

And my Activity is properly extending android.support.v7.app.AppCompatActivity

Any help would be appreciated

Edit: it's apparently related to this DataBindingUtil?


回答1:


I run your code without bindings and its working perfect. You should check your bindings

public class HistoryFragment extends Fragment {

    private ListAdapter mAdapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_history, viewGroup, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //recycler
        RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        // define an adapter
        mAdapter = new ListAdapter(null, getContext());
        recyclerView.setAdapter(mAdapter);
    }

}

even with getContext() it will work and if you are passing null list though it will just not show anything on recycler view but will not give skipping layout error.




回答2:


Pass the correct context to the adapter class

Change this

getContext()

to

getActivity()

It should look like this

mAdapter = new ListAdapter(mWeightData, getActivity(());
        recyclerView.setAdapter(mAdapter);

Also

 RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());

and always pass use getActivity() in fragment:- more info here

Using context in a fragment




回答3:


make some changes like this way if you getting data then show it..

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
private void prepareWeightData() {
    mWeightData = SQLite.select().
            from(WeightData.class).queryList();

    Logger.d(mWeightData.toString()); //The list isn't null, I have data to show
    mAdapter = new ListAdapter(mWeightData, getContext());
    recyclerView.setAdapter(mAdapter);

    mAdapter.notifyDataSetChanged();
}

make some changes in adapter ..

  public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

    private List<WeightData> mList;
    private Context mContext;

    public  class ViewHolder extends RecyclerView.ViewHolder {
        public TextView date, weight;
        public ImageView image;

        public ViewHolder(View v) {
            super(v);
            date = v.findViewById(R.id.text_view_date);
            weight = v.findViewById(R.id.text_view_weight);
            image = v.findViewById(R.id.image);
        }
    }

    public ListAdapter(List<WeightData> plist, Context pContext) {
        this.mList = plist;
        this.mContext = pContext;
    }

    @Override
    public ListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_weight_history, parent, false);

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        //set data
        WeightData weightData = mList.get(position);
        holder.date.setText(weightData.getLastDayWeightMeasurement());
        holder.weight.setText(weightData.getWeight());

    }

    @Override
    public int getItemCount() {
        return mList.size();
    }
}



回答4:


Merging onCreateView and onViewCreated (see below) works for me (the error disappears)

 @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, viewGroup, false);

        //binding variable
        mFragmentHistoryBinding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_first);
        mFragmentHistoryBinding.setVariable(this);

        //recycler
        RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        // define an adapter
        mAdapter = new ListAdapter(mWeightData, getContext());
        recyclerView.setAdapter(mAdapter);

        prepareWeightData();

        return view;
    }

EDIT

Change your adapter like this:

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

    private final List<WeightData> mList;
    //... existing code

    public void updateDataSet(List<WeightData> weightData) {
        mList.clear();
        mList.addAll(weightData);
        notifyDataSetChanged();
    }

    public ListAdapter(Context pContext) {
        this.mList = new ArrayList<>();
        this.mContext = pContext;
        this.mLayoutInflater = LayoutInflater.from(this.mContext);
    }

    //... existing code

}

in onCreateView (updated from below)

  // define an adapter
        mAdapter = new ListAdapter(getContext());
        recyclerView.setAdapter(mAdapter);

        prepareWeightData();

        return view;
    }

prepareWeightData method:

private void prepareWeightData() {
    List<WeightData> weightData = SQLite.select().
            from(WeightData.class).queryList();

    Logger.d(weightData.toString()); //The list isn't null, I have data to show

    mAdapter.updateDataSet(weightData);
}


来源:https://stackoverflow.com/questions/50273294/recyclerview-in-fragment-no-adapter-attached-skipping-layout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!