You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Studio点餐APP:订单存购物车与Firebase及购物车列表实现问询

解决购物车存储与展示的完整方案

针对你开发点餐应用时遇到的两个问题,我整理了一步步的实现方案,结合你已有的代码来完善功能:


1. 完善订单数据存储(本地购物车 + Firebase数据库)

你现有的addToCart调用已经有了雏形,但需要同时处理本地存储和Firebase同步,还要解决重复添加商品的问题。

第一步:完善Order实体类

Firebase需要实体类有空构造函数和完整的getter/setter,确保能正常序列化:

public class Order {
    private String foodId;
    private String foodName;
    private int quantity;
    private double price;

    // Firebase必须的空构造函数
    public Order() {}

    public Order(String foodId, String foodName, int quantity, double price) {
        this.foodId = foodId;
        this.foodName = foodName;
        this.quantity = quantity;
        this.price = price;
    }

    // 所有字段的getter和setter
    public String getFoodId() { return foodId; }
    public void setFoodId(String foodId) { this.foodId = foodId; }
    public String getFoodName() { return foodName; }
    public void setFoodName(String foodName) { this.foodName = foodName; }
    public int getQuantity() { return quantity; }
    public void setQuantity(int quantity) { this.quantity = quantity; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
}
第二步:修改Database类的addToCart方法

让它同时处理本地SQLite存储和Firebase同步,并且支持重复商品的数量累加:

public class Database extends SQLiteOpenHelper {
    // 你的SQLite构造函数和onCreate逻辑(这里省略你已有的部分)

    public void addToCart(Order order) {
        SQLiteDatabase db = this.getWritableDatabase();
        
        // 1. 处理本地SQLite存储:判断商品是否已存在,存在则更新数量
        Cursor cursor = db.rawQuery("SELECT * FROM Cart WHERE foodId=?", new String[]{order.getFoodId()});
        if (cursor.moveToFirst()) {
            int currentQty = cursor.getInt(cursor.getColumnIndex("quantity"));
            int newQty = currentQty + order.getQuantity();
            ContentValues values = new ContentValues();
            values.put("quantity", newQty);
            db.update("Cart", values, "foodId=?", new String[]{order.getFoodId()});
        } else {
            ContentValues values = new ContentValues();
            values.put("foodId", order.getFoodId());
            values.put("foodName", order.getFoodName());
            values.put("quantity", order.getQuantity());
            values.put("price", order.getPrice());
            db.insert("Cart", null, values);
        }
        cursor.close();
        db.close();

        // 2. 同步到Firebase Firestore(假设用户已登录)
        String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
        CollectionReference cartRef = FirebaseFirestore.getInstance()
                .collection("Users")
                .document(userId)
                .collection("Cart");

        cartRef.document(order.getFoodId())
                .get()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        DocumentSnapshot doc = task.getResult();
                        if (doc.exists()) {
                            // 已存在则更新数量
                            int currentQty = doc.getLong("quantity").intValue();
                            cartRef.document(order.getFoodId())
                                    .update("quantity", currentQty + order.getQuantity());
                        } else {
                            // 不存在则添加新记录
                            cartRef.document(order.getFoodId()).set(order);
                        }
                    } else {
                        Log.e("CartError", "Firebase同步失败: " + task.getException().getMessage());
                    }
                });
    }
}

2. 实现点击购物车按钮展示订单列表

需要创建一个购物车页面,通过RecyclerView展示订单数据,步骤如下:

第一步:创建购物车页面CartActivity

首先编写布局文件activity_cart.xml

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

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_cart"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"/>

</LinearLayout>
第二步:创建购物车列表项布局cart_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:orientation="vertical"
    android:background="@drawable/card_border">

    <TextView
        android:id="@+id/tv_food_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textStyle="bold"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp">

        <TextView
            android:id="@+id/tv_quantity"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="14sp"/>

        <TextView
            android:id="@+id/tv_price"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="14sp"
            android:gravity="end"/>
    </LinearLayout>

</LinearLayout>
第三步:创建RecyclerView适配器CartAdapter
public class CartAdapter extends RecyclerView.Adapter<CartAdapter.CartViewHolder> {
    private List<Order> cartList;
    private Context context;

    public CartAdapter(List<Order> cartList, Context context) {
        this.cartList = cartList;
        this.context = context;
    }

    @NonNull
    @Override
    public CartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.cart_item, parent, false);
        return new CartViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull CartViewHolder holder, int position) {
        Order order = cartList.get(position);
        holder.tvFoodName.setText(order.getFoodName());
        holder.tvQuantity.setText("数量: " + order.getQuantity());
        holder.tvPrice.setText("价格: ¥" + order.getPrice());
        // 这里可以添加修改数量、删除商品的逻辑
    }

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

    static class CartViewHolder extends RecyclerView.ViewHolder {
        TextView tvFoodName, tvQuantity, tvPrice;

        public CartViewHolder(@NonNull View itemView) {
            super(itemView);
            tvFoodName = itemView.findViewById(R.id.tv_food_name);
            tvQuantity = itemView.findViewById(R.id.tv_quantity);
            tvPrice = itemView.findViewById(R.id.tv_price);
        }
    }
}
第四步:在CartActivity中加载并展示数据

你可以选择从本地SQLite加载(速度快)或者从Firebase加载(实时同步),这里提供两种方式:

方式一:从本地SQLite加载
public class CartActivity extends AppCompatActivity {
    private RecyclerView recyclerCart;
    private List<Order> cartList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cart);

        recyclerCart = findViewById(R.id.recycler_cart);
        recyclerCart.setLayoutManager(new LinearLayoutManager(this));

        loadLocalCartData();
    }

    private void loadLocalCartData() {
        SQLiteDatabase db = new Database(this).getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM Cart", null);
        
        while (cursor.moveToNext()) {
            Order order = new Order(
                    cursor.getString(cursor.getColumnIndex("foodId")),
                    cursor.getString(cursor.getColumnIndex("foodName")),
                    cursor.getInt(cursor.getColumnIndex("quantity")),
                    cursor.getDouble(cursor.getColumnIndex("price"))
            );
            cartList.add(order);
        }
        cursor.close();
        db.close();

        CartAdapter adapter = new CartAdapter(cartList, this);
        recyclerCart.setAdapter(adapter);
    }
}
方式二:从Firebase加载(实时同步)
private void loadFirebaseCartData() {
    String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
    CollectionReference cartRef = FirebaseFirestore.getInstance()
            .collection("Users")
            .document(userId)
            .collection("Cart");

    cartRef.get().addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            for (QueryDocumentSnapshot doc : task.getResult()) {
                Order order = doc.toObject(Order.class);
                cartList.add(order);
            }
            CartAdapter adapter = new CartAdapter(cartList, CartActivity.this);
            recyclerCart.setAdapter(adapter);
        } else {
            Log.e("CartError", "加载购物车失败: " + task.getException().getMessage());
            Toast.makeText(this, "加载购物车失败", Toast.LENGTH_SHORT).show();
        }
    });
}
第五步:修改购物车按钮的点击事件

在你现有的FoodDetail中,把按钮点击事件改为跳转到CartActivity

btnCart.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 先添加到购物车(保留你原有的逻辑)
        new Database(getBaseContext()).addToCart(new Order(
            foodId, currentFood.getName(), numberButton.getNumber(), currentFood.getPrice()
        ));
        Toast.makeText(FoodDetail.this, "Added To Cart", Toast.LENGTH_SHORT).show();
        
        // 跳转到购物车页面
        Intent intent = new Intent(FoodDetail.this, CartActivity.class);
        startActivity(intent);
    }
});

额外注意事项

  • 确保Firebase已经正确配置到你的项目中(添加google-services.json、依赖等)
  • 处理用户未登录的情况:如果用户未登录,Firebase部分会报错,需要先引导用户登录
  • 数据同步:如果用户在多个设备使用,建议以Firebase数据为准,本地作为缓存
  • 购物车操作:可以添加修改数量、删除商品的功能,记得同时更新本地和Firebase数据

内容的提问来源于stack exchange,提问作者Mary

火山引擎 最新活动