RecyclerView in Fragment: адаптер не подключен, пропускающий макет - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь использовать RecyclerView во фрагменте, но я столкнулся с проблемой, мой список не отображается, и у меня есть эта ошибка:

E / RecyclerView: адаптер не подключен; пропускающий макет

Я проверял решения, видимо проблемы возникали когда:

  • RecyclerView инициализируется после адаптера

  • Привязка и настройка recyclerView в onCreateView вместо onViewCreated

Но я обратил внимание, я попробовал альтернативы, и я все еще сталкиваюсь с той же проблемой.

Вот мой код фрагмента:

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();
    }
}

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>

Код 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();
    }
}

И моя активность правильно расширяется android.support.v7.app.AppCompatActivity

Любая помощь будет оценена

Редактировать: очевидно, это связано с этим DataBindingUtil?

Ответы [ 4 ]

0 голосов
/ 10 мая 2018

У меня работает слияние onCreateView и onViewCreated (см. Ниже) (ошибка исчезает)

 @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

Измените ваш адаптер следующим образом:

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

}

в onCreateView (обновлено снизу)

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

        prepareWeightData();

        return view;
    }

метод prepareWeightData:

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);
}
0 голосов
/ 10 мая 2018

Передайте правильный контекст классу адаптера

Измените это

getContext()

на

getActivity()

Это должно выглядеть следующим образом

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

Также

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

и всегда передавайте use getActivity () во фрагменте: - дополнительная информация здесь

Использование контекста во фрагменте

0 голосов
/ 10 мая 2018

Я запускаю ваш код без привязок, и он отлично работает.Вы должны проверить свои привязки

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

}

даже с getContext (), он будет работать, и если вы передаете нулевой список, хотя он просто ничего не отобразит в представлении переработчика, но не даст пропустить ошибку макета.

0 голосов
/ 10 мая 2018

внесите некоторые изменения, например, если вы получаете данные, а затем покажите их ..

    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();
}

внесите некоторые изменения в адаптер ..

  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();
    }
}
...