摘要:本文基于一个完整的 Android 毕业设计项目,介绍如何构建一款集宠物健康档案、在线商城、宠物社区、订单管理、主题换肤于一体的宠物服务 App。文章结合真实运行截图与核心代码,讲解 ViewPager + Fragment 底部导航、SQLite 本地持久化、OkHttp 网络请求、skin-support 动态换肤等关键技术,适合 Android 初学者及毕设参考。
关键词:Android;宠物健康;SQLite;OkHttp;Fragment;主题换肤;毕业设计
一、项目背景与功能概述
随着养宠人群的增长,围绕宠物的健康管理、社交分享和周边消费逐渐形成一体化需求。本项目是一款面向 Android 端的宠物健康综合服务平台,核心定位是:
- 宠物健康档案:记录宠物年龄、体重、疫苗、洗澡日期等信息;
- 在线商城:猫粮、狗粮等宠物用品浏览、搜索、加购、下单;
- 宠物社区:用户可发布图文、点赞、评论,形成互动;
- 订单管理:个人购买记录与管理员订单视图;
- 主题换肤:支持默认绿、酷黑、梦幻紫三套主题动态切换。
项目采用 Java 开发,源码包为 com.example.order,应用 ID 为 com.example.petHealth,编译 SDK 30,最低支持 Android 5.0(API 21)。
二、技术栈与架构设计
2.1 技术栈
| 技术/框架 | 说明 |
|---|---|
| Android SDK 30 | 编译与构建环境 |
| Java 1.8 | 开发语言 |
| BottomNavigationView + Fragment | 底部导航与页面切换 |
| ViewPager | 商城首页广告轮播 |
| RecyclerView / ListView | 商品、社区、评论等列表展示 |
| SQLite + 7 张表 | 本地数据持久化 |
| OkHttp 4.4.0 | 异步网络请求 |
| Gson 2.8.6 | JSON 序列化与反序列化 |
| Glide 4.11.0 | 图片加载与显示 |
| PictureSelector | 相册选图与头像上传 |
| skin-support 4.0.5 | 动态主题换肤 |
2.2 整体架构
项目采用经典的分层架构:
UI 层:Activity / Fragment / Adapter
│
业务层:Okhttp(网络) + DBHelper 系列 DAO(本地数据库)
│
数据层:entity(本地实体) + bean(网络响应模型) + utils(工具类)
BaseActivity统一处理换肤逻辑;MyApplication全局初始化 skin-support;DBHelper作为 SQLite 单例入口,管理 7 张表的 DAO;Okhttp封装 POST/PUT/GET/DELETE/文件上传等通用网络方法。
三、核心功能模块与运行截图
3.1 登录与注册
启动页 OpenActivity 申请必要权限后进入登录界面。登录区分普通用户与管理员角色,支持离线登录模式。

注册页支持填写用户名、性别、手机号、地址、密码,并可通过相册选择头像。

3.2 宠物健康档案
健康模块是项目的特色功能。HealthFragment 以列表形式展示当前用户的宠物档案,包含年龄、体重、疫苗、上次洗澡时间等关键信息。

点击列表项进入编辑页,支持修改宠物类型、疫苗、洗澡日期、头像等。

3.3 在线商城
UserShopFragment 顶部使用 ViewPager 实现广告轮播,下方为商品列表,支持关键字搜索。

3.4 宠物社区
社区模块展示用户发布的图文帖子,点击可进入详情页查看、点赞、评论。

3.5 商品详情、购物车与订单
商品详情页展示大图、价格、分类,支持加入购物车与立即购买。

购物车支持勾选商品并实时计算总价。

下单后可在"我的订单"中查看历史记录。

3.6 个人中心与主题换肤
"我的"页面提供个人信息、我的订单、个性主题、退出登录、关于软件等入口。

关于页面展示应用 Logo 与简介。

社区详情页支持评论与点赞。

四、数据库设计
应用使用 SQLite 本地数据库 petHealthApp.db,数据库创建时预置了管理员、普通用户、宠物档案、社区帖子及评论等数据,方便离线演示。
主要表结构如下:
| 表名 | 核心字段 | 说明 |
|---|---|---|
user |
id, name, password, address, sex, phone, photo, user_type | 用户表,区分管理员/普通用户 |
Stuff |
id, name, title, kind, price, path, inventory | 商品表 |
cart |
id, username | 购物车关联表 |
Record |
username, id, name, price, address | 订单记录表 |
petBasic |
id, user_id, name, type, birth_date, weight, vaccine_name, shower_date, path | 宠物健康档案 |
community |
id, user_id, title, photo, content, date, likes | 社区帖子 |
communityComments |
id, user_id, community_id, name, comment_text, comment_date | 社区评论 |
建表逻辑集中在 DBHelper.onCreate() 中:
java
// 用户表
String sql = "create table user(id integer primary key autoincrement,name text not null," +
"password text not null,address text not null,sex text not null," +
"phone text not null,photo text not null,user_type text not null)";
sqLiteDatabase.execSQL(sql);
// 宠物健康档案表
sql = "CREATE TABLE petBasic (id integer primary key autoincrement,user_id integer," +
"name text not null, type text not null, birth_date text not null," +
"weight text not null,vaccine_name text not null,shower_date text not null,path text not null)";
sqLiteDatabase.execSQL(sql);
// 社区帖子表
sql = "CREATE TABLE community (id integer primary key autoincrement,user_id integer," +
"title text not null, photo text not null, content text not null," +
"date text not null, likes INTEGER)";
sqLiteDatabase.execSQL(sql);
五、关键代码解析
5.1 换肤框架初始化
MyApplication 中初始化 skin-support,关闭状态栏和窗口背景换肤,避免与系统主题冲突。
java
public class MyApplication extends Application {
public static MyApplication Instance;
public static boolean offlineLogin = true;
@Override
public void onCreate() {
super.onCreate();
Instance = this;
SkinCompatManager.withoutActivity(this)
.addInflater(new SkinAppCompatViewInflater())
.addInflater(new SkinMaterialViewInflater())
.setSkinStatusBarColorEnable(false)
.setSkinWindowBackgroundEnable(false)
.loadSkin();
}
}
5.2 BaseActivity 动态主题切换
所有 Activity 继承 BaseActivity,通过 SPUtils.getTheme() 读取用户保存的主题类型,在 onCreate() 中应用对应颜色。
java
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme();
}
protected void setTheme() {
int type = SPUtils.getTheme(this);
if (type == 0) {
setTheme(R.style.AppTheme);
SkinCompatUserThemeManager.get().addColorState(R.color.colorPrimary,
new ColorState.ColorBuilder()
.setColorDefault("#09C6A0")
.setColorActivated("#09C6A0").build());
} else if (type == 1) {
setTheme(R.style.AppTheme1);
SkinCompatUserThemeManager.get().addColorState(R.color.colorPrimary,
new ColorState.ColorBuilder()
.setColorDefault("#000000")
.setColorActivated("#000000").build());
} else if (type == 2) {
setTheme(R.style.AppTheme3);
SkinCompatUserThemeManager.get().addColorState(R.color.colorPrimary,
new ColorState.ColorBuilder()
.setColorDefault("#6633FF")
.setColorActivated("#6633FF").build());
}
}
@NonNull
@Override
public AppCompatDelegate getDelegate() {
return SkinAppCompatDelegateImpl.get(this, this);
}
}
5.3 底部导航与 Fragment 切换
MainActivity 使用 BottomNavigationView 实现底部 Tab,点击不同菜单项切换对应 Fragment。
java
navigation.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
getSupportFragmentManager().beginTransaction()
.replace(R.id.main, new HealthFragment()).commit();
return true;
case R.id.cart:
if (DBUser.isAdmin()) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main, FragmentMainAdmin.newInstance()).commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main, UserShopFragment.newInstance()).commit();
}
return true;
case R.id.community:
getSupportFragmentManager().beginTransaction()
.replace(R.id.main, new CommunityFragment()).commit();
return true;
case R.id.me:
getSupportFragmentManager().beginTransaction()
.replace(R.id.main, BlankFragment_me.newInstance()).commit();
return true;
}
return false;
}
});
navigation.setSelectedItemId(R.id.home);
5.4 宠物健康数据读写
HealthFragment 从 DBHelper 读取当前用户的宠物档案,使用 PetHealthAdapter 展示;长按可删除,点击可编辑。
java
@Override
public void onResume() {
super.onResume();
petBasic.clear();
petBasic.addAll(DBHelper.GetInstance(getContext()).getDBPetHealth().getAll());
set();
}
void set() {
PetHealthAdapter adapter = new PetHealthAdapter(getContext(),
R.layout.layout_pet_health_list, petBasic);
listview.setAdapter(adapter);
listview.setOnItemClickListener((adapterView, view, i, l) -> {
Intent intent = new Intent();
intent.putExtra("entry", petBasic.get(i));
intent.setClass(getContext(), AddPetHealthActivity.class);
startActivity(intent);
});
listview.setOnItemLongClickListener((parent, view, position, id) -> {
new AlertDialog.Builder(getActivity())
.setMessage("确认要删除该数据吗")
.setPositiveButton("确定", (dialog1, which) -> {
DBHelper.GetInstance(getContext()).getDBPetHealth()
.delete(petBasic.get(position).getId());
petBasic.clear();
petBasic.addAll(DBHelper.GetInstance(getContext()).getDBPetHealth().getAll());
set();
})
.setNeutralButton("取消", (dialog, which) -> dialog.dismiss())
.show();
return true;
});
}
5.5 社区详情点赞与评论
CommunityDetailActivity 使用 RecyclerView 展示评论列表,支持发表评论和点赞切换。
java
like.setOnClickListener(v -> {
if (bean.getLike() == 0) {
like.setImageResource(R.drawable.like);
bean.setLike(1);
} else {
like.setImageResource(R.drawable.unlike);
bean.setLike(0);
}
DBHelper.GetInstance(this).getDBCommunity().change(bean);
});
findViewById(R.id.bt_comment).setOnClickListener(v -> {
if (comment.getText().toString().isEmpty()) {
Toast.makeText(this, "请输入评论", Toast.LENGTH_LONG).show();
return;
}
saveData();
});
private void saveData() {
CommunityComment comment1 = new CommunityComment();
comment1.setComment_text(comment.getText().toString());
comment1.setCommunity_id(bean.getId());
comment1.setName(DBUser.user.getName());
comment1.setComment_date(DBHelper.getDate());
DBHelper.GetInstance(this).getCommunityComment().add(comment1);
update();
}
5.6 OkHttp 网络请求封装
Okhttp 工具类采用单例模式,封装了 GET/POST/PUT/DELETE 及文件上传方法,并通过 initList() 从后端拉取商品列表。
java
public static Okhttp getInstance() {
if (netokhttp == null) {
netokhttp = new Okhttp();
}
return netokhttp;
}
public void postJson(String url, String json, Callback callback) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(http + url)
.post(body)
.build();
Call call = getInstance().initOkHttpClient().newCall(request);
call.enqueue(callback);
}
public void uploadFile(String path, Callback callback) {
File file = new File(path);
RequestBody body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
MultipartBody.create(MediaType.parse("multipart/form-data"), file))
.build();
Request request = new Request.Builder()
.url(http + fileUpload)
.post(body)
.build();
getInstance().initOkHttpClient().newCall(request).enqueue(callback);
}
网络层基础地址配置为:
java
private String http = "http://192.168.3.6:8080/order/";
实际运行前请根据本地后端服务地址修改该 IP。
六、项目运行说明
6.1 环境要求
- Android Studio 4.0+
- JDK 1.8
- Android SDK 30
- Gradle 插件版本与项目配置匹配
6.2 运行步骤
- 使用 Android Studio 打开
petHealthApp模块; - 同步 Gradle,下载依赖;
- 如需联网功能,修改
Okhttp.java中的后端地址; - 连接真机或启动模拟器(建议 API 21 以上);
- 点击 Run 安装运行。
6.3 预置账号
| 账号 | 密码 | 角色 |
|---|---|---|
| admin | 123 | 管理员 |
| 小李 | 123 | 普通用户 |
| 小王 | 123 | 普通用户 |
七、总结与展望
本项目从实际需求出发,将宠物健康管理、电商购物、社区互动整合到一款 Android 应用中,覆盖了登录注册、数据库设计、网络请求、图片选择、主题换肤等常见开发场景,适合作为 Android 课程设计或毕业设计参考。
后续可拓展方向:
- 接入后端真实接口,实现用户注册、商品上下架、订单支付等完整链路;
- 使用 Room 替换原生 SQLite,提升数据库可维护性;
- 引入 MVVM + Jetpack 组件(ViewModel、LiveData)优化架构;
- 增加疫苗提醒、洗澡提醒等定时通知功能;
- 使用 Jetpack Compose 重构 UI,提升开发效率。
如果文章对你有帮助,欢迎点赞、收藏、关注!有问题可以在评论区留言交流。