Fragment,RecyclerView:没有附加适配器;跳过布局

Posted

技术标签:

【中文标题】Fragment,RecyclerView:没有附加适配器;跳过布局【英文标题】:Fragment, RecyclerView: No adapter attached; skipping layout 【发布时间】:2019-04-07 18:36:25 【问题描述】:

我正在使用 Fragment 来查看 RecyclerView。但我总是得到这个错误

E/RecyclerView:没有附加适配器;跳过布局

我为我的 recyclerview 创建了一个适配器,但布局没有显示。 php后端工作正常。有人可以帮忙吗?这是我的片段和适配器代码

Tips.java

public class Tips extends Fragment 

Configuration config = new Configuration();
String HttpUrl = config.viewtips_url;
List<TipModel> tipList;
RecyclerView recyclerView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_tips, container, false);
    recyclerView = view.findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    tipList = new ArrayList<>();
    loadTips();
    return view;


private void loadTips() 
    StringRequest stringRequest = new StringRequest(Request.Method.GET, HttpUrl,
            new Response.Listener<String>() 
                @Override
                public void onResponse(String response) 
                    try 
                        JSONArray jsonArray = new JSONArray(response);
                        for (int i = 0; i < jsonArray.length(); i++) 
                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                            tipList.add(new TipModel(
                                    jsonObject.getInt("id"),
                            jsonObject.getString("tip")

                            ));
                        
                        TipAdapter tipAdapter = new TipAdapter(getActivity(), tipList);
                        recyclerView.setAdapter(tipAdapter);
                     catch (JSONException e) 
                        e.printStackTrace();
                    
                
            ,
            new Response.ErrorListener() 
                @Override
                public void onErrorResponse(VolleyError error) 

                
            );
    Volley.newRequestQueue(getActivity()).add(stringRequest);

TipAdapter.java

public class TipAdapter extends RecyclerView.Adapter<TipAdapter.TipViewHolder> 

private Context context;
private List<TipModel> tipList;

public TipAdapter(Context context, List<TipModel> tipList) 
    this.context = context;
    this.tipList = tipList;


@Override
public TipViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.itemlayout, null);
    return new TipViewHolder(view);


@Override
public void onBindViewHolder(TipViewHolder holder, int position) 
    TipModel tipModel = tipList.get(position);


    holder.textViewTip.setText(tipModel.getTip());



@Override
public int getItemCount() 
    return tipList.size();


class TipViewHolder extends RecyclerView.ViewHolder 
    TextView textViewTip;

    public TipViewHolder(View view) 
        super(view);
        textViewTip = view.findViewById(R.id.textViewTip);
    

【问题讨论】:

你在哪里打电话loadTips() 虽然,你最好 1. 将 adapter 分配给 onCreateViewHolder() 内的 recyclerView,2. 添加一个 adapter.updateWith(List&lt;TipModel&gt; tipList) 3. 并使用从中获取的tipList更新适配器StringRequest @SumitAnantwar 什么?为什么要将适配器分配给适配器 inside 的 RecyclerView? @SumitAnantwar 我已经编辑了上面的代码。尽管 RecyclerView: 没有附加适配器,但布局已经显示;跳过布局错误仍在我的日志中。这是我应该担心的事情吗? 您必须在 Fragment 的onCreateViewHolder() 中分配适配器。您收到此错误是因为在第一个布局周期中,回收器没有附加任何适配器。这主要是错误的。回收器应该附加一个适配器,并且在 StringRequest 之前,适配器的数据存储应该是空的。当StringRequest 完成时,您将传入获取的数据并调用notifyDataSetChanged()。这将使用新数据重新加载回收器。 【参考方案1】:

这是因为RecyclerView在创建视图时调度布局时需要一个适配器,所以如果创建视图时没有适配器也没关系,它会跳过布局部分。

如果您担心错误,那么您可以在创建视图时设置一个空适配器:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    return inflater.inflate(R.layout.fragment_tips, container, false);


@Override
public void onViewCreated(View view, Bundle savedInstanceState) 
    recyclerView = view.findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    tipList = new ArrayList<>();
    recyclerView.setAdapter(new TipAdapter(getActivity(), tipList));

然后在响应回调中调整你的代码:

@Override
public void onResponse(String response) 

    // Instead of setting adapter here...
    // TipAdapter tipAdapter = new TipAdapter(getActivity(), tipList);
    // recyclerView.setAdapter(tipAdapter);

    // Just notify the adapter that tipList has changed.
    recyclerView.getAdapter().notifyDataSetChanged();

    // ...

【讨论】:

此解决方案有效,布局显示完美。虽然我收到了一个新错误“E/ImageInMemoryGraph: PFD pipe transfer failed java.io.IOException: Broken pipe” 对不起,我不确定新错误来自哪里,我在您的代码中看不到任何与图像相关的问题,您可能需要在其他地方寻找错误的来源。跨度> 【参考方案2】:

TipList是Adapter的datastore,属于Adapter,不属于Fragment

我已经编辑了你的代码(无权访问 android Studio,在文本编辑器中进行,请检查语法错误)

片段

public class Tips extends Fragment 

Configuration config = new Configuration();
String HttpUrl = config.viewtips_url;

RecyclerView recyclerView;
TipAdapter tipAdapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    // Initialize the Tip Adapter
    tipAdapter = new TipAdapter(getActivity());

    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_tips, container, false);
    recyclerView = view.findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    // Assign the Adapter to recyclerView
    recyclerView.setAdapter(tipAdapter);
    
    return view;


private void loadTips() 
    StringRequest stringRequest = new StringRequest(Request.Method.GET, HttpUrl,
            new Response.Listener<String>() 
                @Override
                public void onResponse(String response) 
                    try 
                        JSONArray jsonArray = new JSONArray(response);
                        // Create a new TipList
                        List<TipModel> tipList = new ArrayList<>();
                        
                        for (int i = 0; i < jsonArray.length(); i++) 
                            
                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                            tipList.add(new TipModel(
                                jsonObject.getInt("id"),
                                jsonObject.getString("tip")
                            ));
                        
                        
                        tipAdapter.updateWith(tipList)
                        
                     catch (JSONException e) 
                        e.printStackTrace();
                    
                
            ,
            new Response.ErrorListener() 
                @Override
                public void onErrorResponse(VolleyError error) 

                
            );
    Volley.newRequestQueue(getActivity()).add(stringRequest);

提示适配器

public class TipAdapter extends RecyclerView.Adapter<TipAdapter.TipViewHolder> 

private Context context;
private List<TipModel> tipList = new ArrayList<>();

public TipAdapter(Context context) 
    this.context = context;


@Override
public TipViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.itemlayout, null);
    return new TipViewHolder(view);


@Override
public void onBindViewHolder(TipViewHolder holder, int position) 
    TipModel tipModel = tipList.get(position);


    holder.textViewTip.setText(tipModel.getTip());



@Override
public int getItemCount() 
    return tipList.size();


class TipViewHolder extends RecyclerView.ViewHolder 
    TextView textViewTip;

    public TipViewHolder(View view) 
        super(view);
        textViewTip = view.findViewById(R.id.textViewTip);
    


public updateWith(List<TipModel> tipList) 
    this.tipList = tipList;
    notifyDataSetChanged();

【讨论】:

【参考方案3】:

当我在片段中膨胀回收站视图时遇到类似问题时,我就是这样做的。这段代码非常适合我:

附: - 这是我在应用程序中使用的代码补丁。给您带来的不便,我深表歉意。

首先,在 Display Fragment 的 onCreateView() 中:

public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) 
        View root = inflater.inflate(R.layout.fragment_home, container, false);
        Firebase.setAndroidContext(getActivity());
        ((Home_Drawer) getActivity())
                .setActionBarTitle("Home");

        recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view_home_frag);
        progressBar = (ProgressBar) root.findViewById(R.id.mainPageProgressBar);

//        Log.i("inside", "rv initiated" +mLayoutManager.toString());
        // Assign activity this to progress dialog.
        progressDialog = new ProgressDialog(getActivity());

        // Setting up message in Progress dialog.
        progressDialog.setMessage("Loading Images From Firebase.");
        // Showing progress dialog.
        progressDialog.show();
        // The path is already defined in MainActivity.
        databaseReference = FirebaseDatabase.getInstance().getReference().child("productDisplay");
        Log.i("inside", databaseReference.toString());

        return root;
    

然后,我们调用 onStart()。这是因为回收器视图通常不会膨胀,在 onCreateView() 中设置适配器。

@Override
    public void onStart() 
        super.onStart();

        FirebaseRecyclerOptions<DisplayItemsModel> item_info =
                new FirebaseRecyclerOptions.Builder<DisplayItemsModel>()
                        .setQuery(databaseReference, DisplayItemsModel.class)
                        .build();
        final FirebaseRecyclerAdapter<DisplayItemsModel, ViewHolder> info_adapter =
                new FirebaseRecyclerAdapter<DisplayItemsModel, ViewHolder>(item_info) 
                    @Override
                    protected void onBindViewHolder(final ViewHolder holder, final int position, final DisplayItemsModel model) 
                        mContext = getContext();
                        final DatabaseReference dref = getRef(position).getRef();
                        Log.i("dref", dref.toString());
                        // Adding Add Value Event Listener to databaseReference.
                        dref.addValueEventListener(new ValueEventListener() 
                            @Override
                            public void onDataChange(final DataSnapshot snapshot) 

                                holder.item_name_single_card.setText(snapshot.child("name").getValue().toString());
                                holder.price_single_card.setText(snapshot.child("price").getValue().toString());
                                String image_url = snapshot.child("image").getValue().toString();

                                Picasso.get().load(image_url).into(holder.thumbnail);
                        // Continue with your code.

这对我来说非常有效。希望它能解决你的问题。

【讨论】:

以上是关于Fragment,RecyclerView:没有附加适配器;跳过布局的主要内容,如果未能解决你的问题,请参考以下文章

E/RecyclerView:没有附加适配器;在片段内的recyclerview上跳过布局

带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢

在 Fragment 中显示 RecyclerView

Fragment、Volley 和 RecyclerView

单击不在 Fragment 内的 RecyclerView 项目上工作

java Fragment && RecyclerView