简体   繁体   English

RecyclerView 在 Fragment 上不可见

[英]RecyclerView isn't visible on Fragment

I'm following this tutorial to implement a Room database.我正在按照教程来实现 Room 数据库。 Everything is the same except mine is on a Fragment.一切都一样,除了我在一个片段上。 There are no errors and the RecyclerView cards aren't visible at all.没有错误,并且RecyclerView卡根本不可见。 (I'm still able to add cards dynamically when not using a RecyclerView ) (不使用RecyclerView时,我仍然可以动态添加卡片)

I've already tried this on an Activity and it still doesn't work so I must have missed something as I'm not copying the entire code from the tutorial.我已经在 Activity 上尝试过这个,但它仍然不起作用,所以我一定错过了一些东西,因为我没有从教程中复制整个代码。 Maybe it's something simple because I'm new to Android.也许这很简单,因为我是 Android 的新手。

Adapter:适配器:

public class CartItemAdapter extends RecyclerView.Adapter<CartItemAdapter.CartItemHolder> {
    private List<CartItem> cartItems = new ArrayList<>();

    @NonNull
    @Override
    public CartItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.sample_product_item, parent, false);
        return new CartItemHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull CartItemHolder holder, int position) {
        CartItem currentCartItem = cartItems.get(position);
        holder.tvItemName.setText(currentCartItem.getItemName());
        holder.tvItemPrice.setText(currentCartItem.getItemPrice());
        holder.tvQuantity.setText(String.valueOf(currentCartItem.getQuantity()));
    }

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

    public void setCartItems(List<CartItem> cartItems) {
        this.cartItems = cartItems;
        notifyDataSetChanged();
    }

    class CartItemHolder extends RecyclerView.ViewHolder {
        private TextView tvItemName;
        private TextView tvItemPrice;
        private TextView tvQuantity;

        public CartItemHolder(@NonNull View itemView) {
            super(itemView);
            tvItemName = itemView.findViewById(R.id.itemName);
            tvItemPrice = itemView.findViewById(R.id.itemPrice);
            tvQuantity = itemView.findViewById(R.id.quantity);
        }
    }

}

ViewModel:视图模型:

public class CartItemViewModel extends AndroidViewModel {
    private CartItemRepository repository;
    private LiveData<List<CartItem>> allCartItems;

    public CartItemViewModel(@NonNull Application application) {
        super(application);
        repository = new CartItemRepository(application);
        allCartItems = repository.getAllCartItems();
    }

    public void insert(CartItem cartItem) {
        repository.insert(cartItem);
    }

    public void update(CartItem cartItem) {
        repository.update(cartItem);
    }

    public void delete(CartItem cartItem) {
        repository.delete(cartItem);
    }

    public void deleteAllCartItems() {
        repository.deleteAll();
    }

    public LiveData<List<CartItem>> getAllCartItems() {
        return allCartItems;
    }
}

Fragment layout:片段布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:orientation="vertical">

    <!--Views...-->

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/cart_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/totalCard"
        android:layout_below="@id/titleCard"
        android:padding="8dp"
        tools:listitem="@layout/sample_product_item">

        <!-- cart items dynamically added here -->

    </androidx.recyclerview.widget.RecyclerView>

    <!--Views...-->

</RelativeLayout>

Fragment class:片段 class:

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.frag_cart, container, false);
    RecyclerView recyclerView = view.findViewById(R.id.cart_recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setHasFixedSize(true);
        final CartItemAdapter adapter = new CartItemAdapter();
        recyclerView.setAdapter(adapter);

        cartItemViewModel = new ViewModelProvider(getActivity(),
                ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(CartItemViewModel.class);
        cartItemViewModel.getAllCartItems().observe(getActivity(), new Observer<List<CartItem>>() {
            @Override
            public void onChanged(List<CartItem> cartItems) {
                adapter.setCartItems(cartItems);
                Log.i(TAG, "items set!");
            }
        });
    return view;
}

I've populated the database in CartItemDatabase我已经在CartItemDatabase中填充了数据库

@Database(entities = {CartItem.class}, version = 1)
public abstract class CartItemDatabase extends RoomDatabase {

    private static CartItemDatabase instance;

    public abstract CartItemDao cartItemDao();

    public static synchronized CartItemDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    CartItemDatabase.class, "cart_item_database")
                    .fallbackToDestructiveMigration()
                    .addCallback(roomCallback)
                    .build();
        }
        return instance;
    }

    private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            new PopulateDbAsyncTask(instance).execute();
        }
    };

    private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
        private CartItemDao cartItemDao;

        private PopulateDbAsyncTask(CartItemDatabase db) {
            cartItemDao = db.cartItemDao();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            cartItemDao.insert(new CartItem("Bread", "60", 2));
            cartItemDao.insert(new CartItem("Butter", "70", 1));
            return null;
        }
    }

}

What am I doing wrong?我究竟做错了什么? Please ask me if more info is needed.请询问我是否需要更多信息。 Thanks in advance.提前致谢。

Suggestion建议

Learn to debug your code and pinpoint your error.学习调试代码并查明错误。 Most of the errors I get I solve them by debugging.我得到的大多数错误都是通过调试来解决的。 If you don't know what debugging is or how to do it you can google it.如果您不知道调试是什么或如何进行,您可以 google 一下。 It's really simple and it can save you hours of problem solving and it saves you the question altogether.这真的很简单,它可以为您节省数小时的问题解决时间,并且可以完全节省您的问题。

I'm suggesting this because from what you've described, the first thing I'd check is that if my RecyclerView is receiving anything at all.我建议这样做是因为根据您的描述,我首先要检查的是我的 RecyclerView 是否收到任何东西。 I would do this by setting a debug breakpoint inside the getItemCount method of my RecyclerView.我会通过在我的 RecyclerView 的getItemCount方法中设置一个调试断点来做到这一点。 If the value returned is bigger than 0 it means that's OK.如果返回的值大于 0,则表示没关系。

Then I'd proceed to check other steps of my code and this way you can actually see what's wrong and it's very useful to get a better understanding of what's going and how things work.然后我会继续检查我的代码的其他步骤,这样你就可以真正看到哪里出了问题,这对于更好地了解正在发生的事情以及事情是如何工作的非常有用。

This way you can pinpoint your error and ask a more specific question.通过这种方式,您可以查明您的错误并提出更具体的问题。 Instead of quoting your entire code, you could quote just a method or just one line.您可以只引用一个方法或一行,而不是引用整个代码。

EDIT编辑

Great to hear that the problem is within the list.很高兴听到问题在列表中。 Now I see that you're having a problem with it in the first lines of your adapter.现在我发现您在适配器的第一行遇到了问题。 You're creating a new empty list when you do当你这样做时,你正在创建一个新的空列表

private List<CartItem> cartItems = new ArrayList<>();

Maybe you can consider adding a parameter to the adapter such as也许您可以考虑向适配器添加一个参数,例如

public class CartItemAdapter(List<CartItem> cartItems) extends RecyclerView.Adapter<CartItemAdapter.CartItemHolder>

And the you can use that list inside the adapter.您可以在适配器内使用该列表。 It should be already populated.它应该已经被填充。 And in your onCreateView method you could do something like在您的onCreateView方法中,您可以执行类似的操作

// create the list
private List<CartItem> cartItems = new ArrayList<>();

// populate the list with some element or elements
CartItem item = new CartItem(constructor parameters);
cartItems.add(item);

// create the adapter and send the list as a parameter
final CartItemAdapter adapter = new CartItemAdapter(cartItems)
recyclerView.setAdapter(adapter)

And then in your adapter you can use cartItems as you wish然后在您的适配器中,您可以根据需要使用cartItems

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM