首页 > 解决方案 > 应用程序在 RoomDb 中插入数据时崩溃

问题描述

我正在尝试在 RoomDb 中插入数据,但在数据插入时,即使我在线程中编写插入操作,应用程序也会崩溃。我有一个回收器视图适配器类,其中我有一个基于我想要添加的点击侦听器RoomDb 中的数据。

这是我的 logcat 错误:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

下面是我的代码:

ProductAdapter.class

public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ViewHolder> {

List<Product> productList;
Context context;

public ProductAdapter(List<Product> productList, Context context) {
    this.productList = productList;
    this.context = context;
}

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

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

    Product product = productList.get(position);

    holder.productName.setText(product.getName());
    holder.productPrice.setText(product.getPrice());
    Glide.with(context).load(product.getProduct_image()).placeholder(R.color.teal_200).into(holder.productImage);

    holder.productCard.setAnimation(AnimationUtils.loadAnimation(context,R.anim.recycler_anim));

    holder.addToCart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.tick.setVisibility(View.VISIBLE);
            holder.addToCart.setVisibility(View.INVISIBLE);

            ((AppCompatActivity)context).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ProductDb db = ProductDb.getInstance(context);
                    CartProduct  cartProduct = new CartProduct(product.get_id(),product.getName(),product.getProduct_image(),
                                               product.getPrice(),"1");
                    db.productDao().insert(cartProduct);
                }
            });
         }
    });
}

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

public class ViewHolder extends RecyclerView.ViewHolder {

    ImageView productImage,addToCart,tick;
    TextView productName,productPrice;
    CardView productCard;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        productImage = itemView.findViewById(R.id.productImage);
        productName = itemView.findViewById(R.id.productName);
        productPrice = itemView.findViewById(R.id.productPrice);
        productCard = itemView.findViewById(R.id.productCard);
        tick = itemView.findViewById(R.id.tick);
        addToCart = itemView.findViewById(R.id.addToCart);
    }
  }
}

我该如何克服这个问题?

标签: javaandroidandroid-room

解决方案


当您尝试访问主线程上的数据库而不allowMainThreadQueries()在数据库构建器中声明时,将引发此异常。如果你想在主线程上访问数据库,那么构造你的数据库对象,如下所示 Room.databaseBuilder(App.getInstance().getApplicationContext(), AppDatabase.class, DB_NAME).allowMainThreadQueries()

但不建议这样做。使用异步任务或任何其他后台线程进行数据库操作以获得流畅的用户体验

更新:

不推荐使用异步任务。您可以在此检查异步任务的更多替代方案

我使用 RxJava 进行数据库操作的示例代码是

Single.fromCallable(new Callable<Long>() {
        @Override
        public Long call() throws Exception {
            return getProductDao().insert(product);
        }
    }).observeOn(Threads.ui())
            .delaySubscription(1000, TimeUnit.MILLISECONDS)
            .subscribeOn(Threads.io())
            .subscribe(new RxGenListener<Long>() {
                @Override
                public void onSuccess(Long aLong) {
                    listener.onCallback(aLong);
                }
            });

推荐阅读