android电商APP开发实战教程含购物车功能代码

admin 安卓开发 5



是不是想开发一个电商 APP,却被 “商品怎么展示”“购物车数据怎么存” 这些问题难住?跟着教程写商品列表,运行时要么一片空白,要么图片加载不出来;好不容易做了购物车按钮,点完退出 APP 再进来,之前加的商品全没了;更愁的是,代码越写越乱,改个小功能就报错。新手开发电商 APP,最容易在 “数据展示” 和 “状态保存” 这两关卡壳。今天兔子哥就带大家手把手做一个简易电商 APP,从商品列表到购物车功能全实现,每段代码都讲透,跟着做,你也能做出能加购、能看商品的电商 APP!

基础问题:电商 APP 核心模块有哪些?新手该从哪下手?


可能有朋友会问:“电商 APP 看着功能多,零基础真能搞定吗?” 其实电商 APP 的核心功能没那么复杂,拆分成几个模块一步步做就简单多了。咱们新手先搞定这三个核心模块:

  • 商品列表页:用列表展示商品图片、名称、价格,能上下滑动;

  • 购物车功能:能添加商品、显示数量、计算总价;

  • 数据存储:让购物车数据退出 APP 后不丢失,下次打开还在。


网友 “小蔡开发日记” 说:“之前把电商 APP 想复杂了,后来先做商品列表,再慢慢加购物车,居然真的跑起来了!原来拆成小块这么重要。” 所以别被 “电商” 俩字吓住,咱们从最简单的模块开始,一步步搭起来。



第一步:环境准备,这些依赖库得先加上


开发电商 APP,光有基础环境不够,还得装几个 “工具包”,不然图片加载、数据存储都得自己写,特麻烦。咱们先把这些依赖库加上:

必装依赖库,抄作业就行


打开项目里的 “app→build.gradle” 文件,在 dependencies 里加这几个库:
gradle

dependencies {// 图片加载库,商品图片就靠它implementation 'com.github.bumptech.glide:glide:4.15.1'// 数据绑定,少写一堆findViewById代码implementation 'androidx.databinding:viewbinding:7.4.2'// 本地数据库,存购物车数据用implementation 'androidx.room:room-runtime:2.5.2'kapt 'androidx.room:room-compiler:2.5.2'}


加完点右上角 “Sync Now” 同步,等进度条走完,这些库就装好了。

依赖库作用新手易错点
Glide加载商品图片忘记加网络权限,图片全是问号
ViewBinding简化控件绑定布局文件没启用,报绑定错误
Room本地存储购物车实体类没加注解,存不了数据


兔子哥得多嘴说一句:依赖库版本别乱换,就用教程里的,新版本可能有兼容性问题,新手折腾不起。



第二步:商品列表页,让商品 “显形”


商品列表是电商 APP 的 “脸面”,得先让商品图片、名称、价格正确显示出来。咱们分三步做:

步骤 1:定义商品数据结构


新建 “data→Goods.kt”,告诉 APP 商品有哪些信息:
kotlin

data class Goods(val id: Int, // 商品唯一IDval name: String, // 商品名称val price: String, // 商品价格val imageUrl: String // 商品图片地址,用网络图片链接)


这里的 imageUrl 可以用网上找的免费图片链接,比如 “https://img.example.com/goods1.jpg”,新手别自己 PS 图片,先用现成的测试。

步骤 2:设计列表 item 布局


在 “res→layout” 里新建 “item_goods.xml”,每个商品项长这样:
xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="120dp"android:padding="10dp"android:gravity="center_vertical"android:orientation="horizontal"><ImageViewandroid:id="@+id/ivGoods"android:layout_width="80dp"android:layout_height="80dp"android:scaleType="centerCrop"/><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_marginStart="10dp"android:orientation="vertical"><TextViewandroid:id="@+id/tvName"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp"android:textStyle="bold"/><TextViewandroid:id="@+id/tvPrice"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:textColor="#FF0000"android:textSize="14sp"/>LinearLayout><Buttonandroid:id="@+id/btnAddCart"android:layout_width="wrap_content"android:layout_height="40dp"android:text="加入购物车"/>LinearLayout>


这个布局左边是图片,中间是名称和价格,右边是加购按钮,简单又实用。

步骤 3:写列表逻辑,让商品显示出来


在 MainActivity 里用 RecyclerView 展示商品列表,代码里用模拟数据先测试:
kotlin

class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBinding// 模拟商品数据private val goodsList = listOf(Goods(1, "纯棉T恤", "¥59", "https://img.example.com/tshirt1.jpg"),Goods(2, "休闲牛仔裤", "¥129", "https://img.example.com/pants1.jpg"),Goods(3, "运动鞋", "¥299", "https://img.example.com/shoes1.jpg"))override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// 设置RecyclerViewbinding.rvGoods.layoutManager = LinearLayoutManager(this)binding.rvGoods.adapter = GoodsAdapter(goodsList) { goods ->// 点击加购按钮的逻辑,后面写购物车时补全Toast.makeText(this, "${goods.name}已加入购物车", Toast.LENGTH_SHORT).show()}}}// 适配器代码class GoodsAdapter(private val goodsList: List<Goods>,private val onAddCartClick: (Goods) -> Unit) : RecyclerView.Adapter<GoodsAdapter.ViewHolder>() {inner class ViewHolder(val binding: ItemGoodsBinding) : RecyclerView.ViewHolder(binding.root)override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val binding = ItemGoodsBinding.inflate(LayoutInflater.from(parent.context), parent, false)return ViewHolder(binding)}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val goods = goodsList[position]holder.binding.apply {tvName.text = goods.nametvPrice.text = goods.price// 用Glide加载图片Glide.with(ivGoods.context).load(goods.imageUrl).into(ivGoods)// 加购按钮点击事件btnAddCart.setOnClickListener { onAddCartClick(goods) }}}override fun getItemCount() = goodsList.size}


代码解析:

  • 用 ViewBinding 简化控件绑定,不用写 findViewById;

  • Glide 加载网络图片,记得在 AndroidManifest.xml 加网络权限

  • 适配器里给加购按钮设置点击事件,暂时用 Toast 提示,后面接入购物车。




第三步:购物车功能,数据存本地不丢失


购物车最核心的需求是 “退出 APP 后数据不丢”,咱们用 Room 数据库实现持久化存储:

步骤 1:定义购物车实体和数据库


新建 “database→CartEntity.kt”(购物车数据结构):
kotlin

@Entity(tableName = "cart")data class CartEntity(@PrimaryKey val goodsId: Int, // 用商品ID当主键,避免重复添加val name: String,val price: String,var count: Int // 商品数量,可修改)


新建 “database→AppDatabase.kt”(数据库类):
kotlin

@Database(entities = [CartEntity::class], version = 1, exportSchema = false)abstract class AppDatabase : RoomDatabase() {abstract fun cartDao(): CartDaocompanion object {// 单例模式,避免重复创建数据库@Volatileprivate var INSTANCE: AppDatabase? = nullfun getInstance(context: Context): AppDatabase {return INSTANCE ?: synchronized(this) {val instance = Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"cart_database").allowMainThreadQueries() // 允许主线程操作,新手简化用.build()INSTANCE = instanceinstance}}}}


新建 “database→CartDao.kt”(数据库操作接口):
kotlin

@Daointerface CartDao {@Query("SELECT * FROM cart")fun getAll(): List<CartEntity> // 获取所有购物车商品@Insert(onConflict = OnConflictStrategy.REPLACE)fun insert(cart: CartEntity) // 添加商品,重复时更新@Updatefun update(cart: CartEntity) // 更新数量@Deletefun delete(cart: CartEntity) // 删除商品}


步骤 2:写购物车管理类,处理业务逻辑


新建 “CartManager.kt”,封装购物车操作:
kotlin

class CartManager(context: Context) {private val cartDao = AppDatabase.getInstance(context).cartDao()// 添加商品到购物车,已存在则数量+1fun addToCart(goods: Goods) {val cartList = cartDao.getAll()val existingCart = cartList.find { it.goodsId == goods.id }if (existingCart != null) {// 已存在,数量+1existingCart.count++cartDao.update(existingCart)} else {// 新商品,数量设为1cartDao.insert(CartEntity(goods.id, goods.name, goods.price, 1))}}// 获取购物车所有商品fun getCartList() = cartDao.getAll()// 更新商品数量fun updateCount(cart: CartEntity, newCount: Int) {if (newCount <= 0) return // 数量不能小于1cart.count = newCountcartDao.update(cart)}// 删除商品fun deleteCart(cart: CartEntity) {cartDao.delete(cart)}}


步骤 3:在商品列表调用购物车功能


修改 MainActivity 的加购点击事件:
kotlin

// 在onCreate里初始化CartManagerprivate val cartManager by lazy { CartManager(this) }// 修改适配器的点击事件binding.rvGoods.adapter = GoodsAdapter(goodsList) { goods ->cartManager.addToCart(goods)Toast.makeText(this, "${goods.name}已加入购物车,当前数量:${cartManager.getCartList().find { it.goodsId == goods.id }?.count ?: 1}", Toast.LENGTH_SHORT).show()}


这样点击 “加入购物车”,商品就会存到数据库,退出 APP 再打开,数据依然存在。



常见错误解决,新手常在这里栽跟头


错误 1:商品图片加载不出来,显示灰色问号


现象:列表文字正常,图片是灰色占位符。
原因:没加网络权限,或者图片链接无效,也可能 Glide 没同步好。
解决:检查 AndroidManifest.xml 有没有;用浏览器打开图片链接,确认能访问;重新同步依赖(点 “Sync Now”)。

错误 2:购物车数据存不进去,getAll () 返回空列表


现象:加购后调用 getCartList (),结果是空的。
原因:Room 实体类没加@Entity注解,或者数据库操作没调用。
解决:给 CartEntity 加@Entity(tableName = "cart");检查 addToCart () 是否真的被调用,加购按钮有没有绑定点击事件。

错误 3:退出 APP 后购物车数据丢失


现象:重新打开 APP,购物车列表为空。
原因:没用到 Room 的单例模式,每次创建新数据库实例;或者没调用 insert 方法。
解决:严格用 AppDatabase 的 getInstance () 获取数据库;加购时确保调用了 cartManager.addToCart (goods)。



自问自答:新手开发购物车常见疑问


商品数据一定要用网络图片吗?本地图片可以吗?


当然可以!新手测试时用本地图片更稳定。把图片放到 “res→drawable” 文件夹,imageUrl 写成 “drawable:// 图片名”,Glide 同样能加载,还不用加网络权限,适合初期调试。

购物车页面怎么实现?能显示商品列表和总价吗?


很简单!新建 CartActivity,用 RecyclerView 展示 cartManager.getCartList () 的数据;总价可以遍历列表,把每个商品的价格转成数字,乘以数量后相加,最后显示在 TextView 里,大家可以自己试试。

Room 允许主线程操作,正式开发可以吗?


正式开发不建议!这里为了简化代码加了allowMainThreadQueries(),实际项目要用协程或线程池,避免卡顿。但新手先实现功能,后面再优化性能,别一开始就卡在用不用主线程上。



最后说点实在话


开发电商 APP,新手别想着一步到位,先实现 “能展示商品、能加购物车” 的基础功能,再慢慢加详情页、结算这些复杂功能。我第一次做购物车时,因为没加单例模式,每次打开数据库都是新的,数据存了等于没存,折腾半天才发现问题。
其实核心就是 “拆模块 + 多测试”:先做列表展示,能看到商品;再做购物车存储,确保数据不丢;每个模块做好后单独测试,没问题再往下走。代码报错别慌,大部分问题都是小细节,比如注解漏加、权限没加,耐心查就能解决。
现在你已经有了能展示商品、能存购物车的基础电商 APP,这就是很好的开始!接下来可以试试做购物车页面,显示商品数量和总价,一步步完善。记住,开发 APP 最有趣的就是看着功能从无到有,动手练起来,你会越来越熟练!

标签: com.github.bumptech.glide androidx.databinding

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~