【问题标题】:Fragment, RecyclerView: No adapter attached; skipping layoutFragment,RecyclerView:没有附加适配器;跳过布局
【发布时间】: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()。这将使用新数据重新加载回收器。

标签: android android-recyclerview


【解决方案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.
    

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

    【讨论】:

      猜你喜欢
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-15
      • 2021-11-04
      • 2020-01-09
      • 2017-12-01
      • 2021-06-19
      相关资源
      最近更新 更多