簡體   English   中英

RecyclerView 不調用 onCreateViewHolder 或 onBindView

[英]RecyclerView not calling onCreateViewHolder or onBindView

沒有收到任何錯誤,所有數據似乎都有效。 由於某種原因,調用了與視圖相關的方法。 我已確定以下內容:

  • getItemCount() 是唯一被調用的適配器方法,它返回一個正整數值,(我知道這將是你們會關注的領域)

    • 正在調用構造函數,成員變量有效。

    • Parent View是一個垂直的LinearLayout; 沒有滾動視圖,或任何其他具有自己滾動屬性的視圖。

    • 包含片段視圖被創建並顯示在屏幕上。

這是片段中的聲明,后面是適配器。 任何幫助將不勝感激,因為這完全令人困惑。

SubMenuAdapter adapter = new SubMenuAdapter(getActivity(), mContentItems);
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);
public class SubMenuAdapter extends RecyclerView.Adapter<SubMenuAdapter.ViewHolder> {
private static final String TAG = String.format("==> %S", SubMenuAdapter.class.getSimpleName());

private final List<ContentItem> mContentItems;
private Context mContext;

public SubMenuAdapter(Context context, List<ContentItem> contenItems) {
    Log.d(TAG, "Constructor called");
    mContentItems = contenItems;
    mContext = context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Log.d(TAG, "onCreateViewHolder called");
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_resource_efficiency, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    Log.d(TAG, "onBindViewHolder called");

    ContentItem item = mContentItems.get(position);
    holder.textName.setText(item.getName());
    FontSetter.setMyriadProRegular(mContext, holder.textName);
    Picasso.with(mContext).load("file://" + item.getPreviewImageDefault()).into(holder.imageIcon);
}

@Override
public int getItemCount() {
    Log.d(mContext, String.format("getItemCount: %d", mContentItems.size()));
    return mContentItems.size();
}

// ViewHolder
public static class ViewHolder extends RecyclerView.ViewHolder {

    TextView textName;
    ImageView imageIcon;

    public ViewHolder(View view) {
        super(view);
        textName = (TextView) view.findViewById(R.id.tv_resource_efficiency_option);
        imageIcon = (ImageView) view.findViewById(R.id.iv_resource_efficiency_icon);
    }
}

這也可能對某人有所幫助

首次使用

recyclerView.setAdapter(adapter);

進而:

recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

所以它看起來像這樣:

recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

順序顛倒了

更新:

現在我只是使用:

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

在 xml 中的RecyclerView

追了一個多小時的答案。

在設置適配器之前,不要忘記調用此襯墊。

recyclerView.setLayoutManager(new LinearLayoutManager(this));

似乎回收器視圖沒有內置默認布局管理器選項,因此我們必須以編程方式添加它。

如果您覺得有幫助,請干杯。

確保回收視圖不是來自nestedscrollview 的子視圖

例如,此代碼將不起作用。

<android.support.v4.widget.NestedScrollView
    android:id="@+id/responder_scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/darkGray"
    android:clipToPadding="false"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            app:cardElevation="@dimen/spacing_medium"
            app:cardUseCompatPadding="true">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:id="@+id/responder_testimonial"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentTop="true"
                    android:text="Testimonial"
                    android:textSize="@dimen/general_font_size" />

                <TextView
                    android:id="@+id/responder_counter_testimonial"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_toRightOf="@+id/responder_testimonial"
                    android:text="170"
                    android:textSize="@dimen/general_font_size_small" />

                <Button
                    android:id="@+id/responder_btn_testimonial"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_alignParentTop="true"
                    android:text="Go" />

               <view
                    android:id="@+id/responder_list_testimonial"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_below="@+id/responder_testimonial"
                    class="android.support.v7.widget.RecyclerView"/>
            </RelativeLayout>
        </android.support.v7.widget.CardView>

    </FrameLayout>
</android.support.v4.widget.NestedScrollView>

然后我用,

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<view
    android:id="@+id/responder_list_testimonial"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/responder_testimonial"
    class="android.support.v7.widget.RecyclerView"/>

我不知道這是否對任何人都有幫助,但我幾乎遇到了同樣的問題。 我的問題不在於片段/類,也不在於回收器適配器。 問題出在父 XML 布局中,其中操作FrameLayout采用了match_parent ,其中FrameLayout片段被替換的地方)沒有任何可用的位置來顯示。 這就是沒有調用這些方法的原因。

我想那些面臨同樣問題的人可能會遇到類似的情況。 仔細檢查每個 XML 文件中的每個寬度和高度可能在同一棵樹中,因為問題似乎根本不在適配器中。

我的兩便士在這里。 只花了三個多小時調試這個。

確保您沒有不小心使用以下行。

recyclerView.setHasFixedSize(true);

僅當您確定視圖具有恆定大小時才設置固定大小。 如果不是,則可能根本不會調用 onCreateViewHolder 和 onBindView 方法。

我也遇到了同樣的問題,即onCreateViewHolderonBindView方法沒有被調用,只有getItemCount被調用。 所以基本上是RecyclerView的高度和重量設置為wrap_content0dp 將其更改為某個值后解決了問題。

這已經很老了,但就我而言,我使用的是ConstraintLayout並且高度設置錯誤,因此我的視圖將具有0dp ,然后適配器將保存以完成其工作,因為視圖是 0dp。

確保高度和寬度正常並且RecyclerView具有正大小。

如果您將 wrap_content 作為列表的高度以及項目列表的高度,則不會顯示任何內容並且不會調用任何 recyclerView 函數。

就我而言,在將 Activity 更改為 ViewModel 並使用 Binding 后,我忘記從onCreate方法中刪除setContentView 通過刪除它,我的問題解決了。

在實現 FirebaseListAdapter 時,需要注意以下幾點才能正確設置。

  1. 檢查 xml 中的 recyclerview 是否具有正確的所有屬性。 例如,不要為高度和寬度使用換行內容。
  2. 請檢查是否設置了 layoutManager 並處理了 setHasFixedSize()。
  3. 制作 POJO 類變量,以便它們匹配 firebase 子屬性。
  4. FirebaseRecyclerOptions 已設置。
  5. FirebaseRecyclerAdapter 的 onCreateViewHolder() 和 onBindViewHolder 在那里。
  6. 生命周期事件得到處理。

注意 -使用 wrap_content 作為 recyclerview 的高度是任何人都可能犯的最簡單的錯誤之一。 所以一定要先檢查一下。

我知道這個話題很老,但如果你和我一樣犯了同樣的學習錯誤,你可能會發現這很有幫助。

當我在一些關於 RecyclerView 的網站上學習並復制一些代碼並適應我的上下文時,我創建了不同的變量(例如用戶和數據),它們旨在做同樣的事情,除了一些方法調用數據,一些方法調用用戶. 當您試圖理解其他人的代碼和 Java 功能時,這是一個很容易犯的錯誤(它一直發生在我身上)。

很高興知道您可以在 Java 代碼的任何位置在控制台中 println,因此您可以非常輕松地進行調試。

祝你好運!

就我而言,它使用的是 setHasStableIds(true); 在適配器中,而某些列表項在 getItemID() 中返回 -1,所以我想 RecyclerView 認為它們是相等的。

在我的情況下,有一個FragmentRecyclerView一個內部ViewPager 出現問題是因為我使用Fragment.getFragmentManager()而不是Fragment.getChildFragmentManager作為FragmentStatePagerAdapter的構造函數。

PS Using Layout Inspector 可能對調試此類問題有很大幫助。

請注意您正在使用適配器的線程。
在我的情況下,問題是當我的數據來自服務時從活動中調用notifyDataSetChanged() 實際上該方法是從后台線程調用的。 但是應用程序沒有崩潰,Logcat (!) 中什么也沒有。
所以我在 UI 線程中被稱為notifyDataSetChanged()並且問題解決了。

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

就我而言,我將回收器視圖適配器設置為recyclerview.apply { adapter = adapter }

兩者都指的是 getAdapter() 因此將我的適配器變量名稱重命名為 folderAdapter

如果將 viewpager 放在滾動視圖中,有時會出現此錯誤,這將縮小父視圖以及 viewpager 及其子片段。 因此,如果現在要為子片段找到視圖,則不會調用 onCreateView 和 onBindView 方法。 只需刪除滾動視圖或為您的布局添加權重,這樣視圖就不會縮小。

我有同樣的問題,既沒有調用 onCreateViewHolder 也沒有調用 onBindViewHolder 。 更改您的 onCreateViewHolder 方法以使用您在構造函數中保存引用的 Context 而不是執行 parent.getContext() 應該修復它:

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Log.d(TAG, "onCreateViewHolder called");
    View view = LayoutInflater.from(mContext).inflate(R.layout.row_resource_efficiency, parent, false);
    return new ViewHolder(view);

就我而言,我將 RecyclerView 的 ID 設置為“recyclerView”。 這個 ID 似乎已經在某處定義了,因為當我將它更改為不同的 ID 時,來自適配器的方法被正確調用。

鏈接到答案

我最近遇到了這個問題,顯然有很多可能的原因。 嘗試這些選項中的一個或組合,看看哪一個適合你:)

1. 布局管理器
確保您將布局管理器設置為您的回收站視圖,如下所示

// create a layout manager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(my_context);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

// get recycler view
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_id);
// set
recyclerView.setLayoutManager(linearLayoutManager);

2. 固定尺寸
確保您說明您的回收站視圖是否具有固定大小

// set fixed size
recyclerView.setHasFixedSize(true); // or false depending on implementation

3. XML
確保你的回收器沒有嵌套在太多可能導致混淆的布局中,例如 ScrollView 和 RelativeLayout 的組合。 簡單點,看看能不能解決你的問題

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<android.support.v7.widget.RecyclerView
android:id="@+id/thread_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

如果在設置 recyclerview 高度以匹配父級 (0) 時使用約束布局,則會出現此問題

我有以下情況:

@Override
    protected void onStart() {
        super.onStart();
        Log.d("OnStart","Calling OnStart.");
        FirebaseRecyclerOptions<Data> options = new FirebaseRecyclerOptions.Builder<Data>().setQuery(mDatabase, new SnapshotParser<Data>() {
            @NonNull
            @Override
            public Data parseSnapshot(@NonNull DataSnapshot snapshot) {
                Log.d("parseSnapshot",snapshot.child("name").getValue().toString());
                return new Data(snapshot.child("name").getValue().toString(),
                        snapshot.child("description").getValue().toString(),
                        snapshot.child("id").getValue().toString(),
                        snapshot.child("date").getValue().toString());
            }
        }).build();
        FirebaseRecyclerAdapter<Data,MyViewHolder> adapter = new FirebaseRecyclerAdapter<Data, MyViewHolder>(options) {
            @Override
            protected void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i, @NonNull Data data) {
                Log.d("OnBindViewHolder",data.getName());
                myViewHolder.setName(data.getName());
                myViewHolder.setDescription(data.getDescription());
                myViewHolder.setDate(data.getDate());
            }

            @NonNull
            @Override
            public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                Log.d("OnCreateViewHolder","Creating the viewHolder");
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemlayout,parent,false);
                return new MyViewHolder(view);
            }
        };
        recyclerView.setAdapter(adapter);
        Log.d("OnStart","Exiting OnStart.");
    }

和 OnCreateViewHolder 和 OnBindViewHolder 沒有被調用。

就我而言,我一直在使用分頁庫和 PagingDataAdapter。 在所有數據都已經從 PagingSoure 中獲取並且 RecyclerView 沒有顯示任何內容之后,我設置了一個適配器。 我通過在設置適配器后調用adapter.refresh()解決了這個問題。 像這樣:

recyclerView.adapter = myAdapter
myAdapter.refresh()

我有同樣的問題。 在我的情況下,recyclerView 在幾次刷新后變空了。 例如,當我單擊一個項目並從另一個活動中返回時。 我有數據,但數據沒有設置為 recyclerView 並且沒有錯誤。

我在onCreate方法上創建了 recyclerView,如下所示:

        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL);
        binding.recyclerCommodityList2.setLayoutManager(staggeredGridLayoutManager);
        binding.recyclerCommodityList2.addItemDecoration(new GridSpacingItemDecoration(2, 0, true));
        adapterCommodityList = new RecyclerAdapterMyCommoditiAndPost(cardList.getCard(), context);
        binding.recyclerCommodityList2.setAdapter(adapterCommodityList);

        binding.recyclerCommodityList2.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) {
                visibleItemCount = staggeredGridLayoutManager.getChildCount();
                totalItemCount = staggeredGridLayoutManager.getItemCount();

                if (dy > 0) { //check for scroll down

                    pastVisibleItems = staggeredGridLayoutManager.findFirstVisibleItemPositions(null)[1];

                    if ((visibleItemCount + pastVisibleItems) >= totalItemCount / 2 ) {

                        if (loading) {
                            loading = false;
                            callGetListOfCommodity(selectedCategory); // call api again
                        }
                    }

                }
            }
        });

我將數據放在 api onResponse 方法上,如下所示:

adapterCommodityList = new RecyclerAdapterMyCommoditiAndPost(result.getCard(), MyTamukActivity.this);
binding.recyclerCommodityList2.setAdapter(adapterCommodityList);

所以我在 onResponse 方法上坐了一個新的布局管理器。 像這樣 :

StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL);
binding.recyclerCommodityList2.setLayoutManager(staggeredGridLayoutManager);

adapterCommodityList = new RecyclerAdapterMyCommoditiAndPost(result.getCard(), MyTamukActivity.this);
binding.recyclerCommodityList2.setAdapter(adapterCommodityList);

該解決方案有效,但有時 recyclerView 仍然為空。

所以這是我的最終解決方案:

我從 onCreate 中刪除了 recyclerView 然后我在onResume方法上創建了 recyclerView 而不是那個。 所以布局管理器總是正確地坐在 recyclerView 上。

無論如何,如果您有同樣的問題,請檢查您的布局管理器以及如何在 recyclerView 上設置它。

如果將 recyclerview 放在滾動視圖中,請將滾動視圖替換為 NestedScrollView 並將此行放在 recyclerview 標記中

            android:overScrollMode="never"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM