news 2026/8/23 6:46:47

基于 Android 的校园信息管理系统源码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Android 的校园信息管理系统源码

摘要:本文以一个面向高校的 Android 校园信息管理系统(campusInfoApp)为案例,从架构设计、核心模块实现、关键技术选型三个维度展开分析,详细阐述 MVP 分层、角色路由、主题换肤、网络封装等工程化实践,为同类校园移动应用开发提供参考。


一、项目概述

1.1 项目背景

随着高校信息化建设的推进,学生和管理员对校园信息服务的需求日益多元化——新闻公告浏览、选课操作、请假审批、通知发布等功能分散在不同系统中,用户体验割裂。本项目旨在构建一款一站式校园信息管理 Android 应用,将多场景业务整合至统一入口。

1.2 功能矩阵

功能模块学生端管理员端
用户体系注册 / 登录 / 个人信息 / 修改密码同左
新闻公告浏览列表 + 查看详情发布 / 编辑 / 删除
通知公告浏览列表 + 查看详情发布 / 管理
请假管理提交请假申请(含图片附件)审批 / 查看列表
选课系统课程查询 / 选课 / 已选课程查看添加课程 / 管理课程列表
主题换肤三套皮肤切换(经典/养眼/流行)同左

1.3 应用截图

图 1 — 学生首页功能入口

首页采用卡片式布局,以图标+文字的形式展示六大功能入口:校园新闻、查询课表、请假、选课、发班级通知、微信订阅号。底部为自定义 RadioButton 导航栏(首页/学生管理/我的),管理员登录后自动显示"学生管理"Tab。

图 2 — 注册页面

注册页面支持头像上传(通过 PictureSelector 选择相机或相册)、用户名/昵称/性别/手机号/专业/密码等字段录入,表单校验在客户端完成。

图 3 — 课表查询页面

课表查询以班级为单位展示(软工1班~4班),点击进入对应班级的课程详情,数据来源于本地 SQLite 预置 + 远程服务端同步。


二、技术栈与依赖

2.1 基础配置

配置项
Application IDcom.mmsx.campush
compileSdkVersion30
targetSdkVersion29
minSdkVersion21(覆盖 Android 5.0+)
源文件规模58 个 Java 文件 + 32 个布局 XML

2.2 核心依赖

// build.gradle 核心依赖implementation'com.squareup.okhttp3:okhttp:4.4.0'// HTTP 客户端implementation'com.google.code.gson:gson:2.8.6'// JSON 序列化implementation'com.github.bumptech.glide:glide:4.11.0'// 图片加载implementation'jp.wasabeef:glide-transformations:3.3.0'// 图片变换(圆角等)implementation'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0'// 图片选择器implementation'skin.support:skin-support:4.0.5'// 换肤框架implementation'androidx.recyclerview:recyclerview:1.1.0'// 列表组件

说明build.gradle中声明了 Retrofit 和 RxJava 依赖,但实际代码中网络层采用OkHttp 原生封装Okhttp.java单例工具类),未使用 Retrofit/RxJava 组合。这属于开发过程中的技术决策调整——对于接口数量有限的中型应用,直接使用 OkHttp 足够简洁高效。


三、架构设计

3.1 整体架构

项目采用经典的Activity + Fragment 主从结构,辅以工具层和数据层的分层组织:

┌─────────────────────────────────────────────┐ │ UI 层 │ │ Activity (容器) → Fragment (内容页) │ │ BaseActivity → 具体业务 Activity │ ├─────────────────────────────────────────────┤ │ 适配器层 │ │ NewsAdapter / LeaveAdapter / SelectionAdapter ... ├─────────────────────────────────────────────┤ │ 工具层 │ │ Okhttp (网络) / SPUtils (持久化) │ │ GlideEngine (图片) / JsonUtils (解析) │ ├─────────────────────────────────────────────┤ │ 数据层 │ │ MySqliteOpenHelper (SQLite) │ │ Bean (数据实体) │ └─────────────────────────────────────────────┘

3.2 应用启动流程

应用启动时经历以下关键链路:

Application.onCreate() └─ SkinCompatManager 初始化换肤框架 ↓ OpenActivity (欢迎页) ├─ CountDownTimer 5秒倒计时 ├─ 检查 SPUtils.AUTO_LOGIN 是否启用 │ ├─ 是 → Okhttp.byAccount() 验证有效性 → MainActivity │ └─ 否 → LoginActivity ↓ LoginActivity ├─ 验证码生成(随机4位字母数字) ├─ 记住密码 / 自动登录(SPUtils 持久化) └─ Okhttp.byAccount() 远程验证 → 写入用户角色 → MainActivity ↓ MainActivity (主框架) ├─ 读取 SPUtils.USER_TYPE 判断角色 ├─ 学生 → [StudentHomeFragment, UserFragment] └─ 管理员 → [AdminHomeFragment, UserManageFragment, UserFragment]

3.3 角色路由机制

这是本项目的核心设计之一。MainActivity通过SharedPreferences中存储的USER_TYPE字段决定加载哪套 Fragment 组合:

// MainActivity.java - 角色判断逻辑userType=ConverterUtils.toInt(SPUtils.get(myActivity,SPUtils.USER_TYPE,""));// 管理员隐藏"学生管理"Tab(学生不显示)rbManege.setVisibility(userType==UserTypeEnum.User.getCode()?View.GONE:View.VISIBLE);// "我的"Tab 根据角色映射到不同索引switchFragment(userType==UserTypeEnum.User.getCode()?1:2);

UserTypeEnum定义了三种角色类型:

枚举值含义导航 Tab 数量
User(0)普通学生2 个(首页 + 我的)
Admin(1)管理员3 个(首页 + 学生管理 + 我的)
Dean(2)教学院长3 个(同管理员)

Fragment 采用懒加载 + show/hide模式,避免重复创建:

privatevoidswitchFragment(intfragmentIndex){FragmentTransactiontransaction=getFragmentManager().beginTransaction();if(fragments[fragmentIndex]==null){// 按角色创建对应 Fragment 实例fragments[fragmentIndex]=userType==UserTypeEnum.User.getCode()?newStudentHomeFragment()/newUserFragment():newAdminHomeFragment()/newUserManageFragment()/newUserFragment();transaction.add(R.id.ll_main_content,fragments[fragmentIndex]);}for(inti=0;i<fragments.length;i++){if(fragmentIndex!=i&&fragments[i]!=null)transaction.hide(fragments[i]);// 隐藏其他 Fragment}transaction.show(fragments[fragmentIndex]);transaction.commit();}

四、核心模块技术实现

4.1 网络层封装:OkHttp 工具类

项目将 OkHttp 封装为单例工具类Okhttp.java,统一管理所有 HTTP 交互:

publicclassOkhttp{privateStringhttp="http://192.168.3.6:8080/camplus/";// 服务端基础地址privatestaticOkhttpnetokhttp;publicfinalOkHttpClientclient;privateOkhttp(){client=newOkHttpClient.Builder().readTimeout(2000,TimeUnit.MILLISECONDS)// 读超时 2s.connectTimeout(3000,TimeUnit.MILLISECONDS)// 连接超时 3s.build();}// 单例获取publicstaticOkhttppostNetokhttp(){...}}

提供五种标准 REST 操作方法:

方法HTTP 动词用途
postJson(url, json, callback)POST新增数据(JSON Body)
putJson(url, json, callback)PUT更新数据
getJson(url, callback)GET查询列表
deleteJson(url, id, callback)DELETE按 ID 删除
uploadFile(path, callback)POST (Multipart)图片文件上传
byAccount(account, callback)GET按账号查询用户

所有请求均采用异步回调模式(enqueue(callback)),在onResponse回调中通过JsonUtils将响应字符串反序列化为对应的 Bean 对象:

// 典型的调用模式Okhttp.postNetokhttp().byAccount(account,newCallback(){@OverridepublicvoidonResponse(Callcall,Responseresponse)throwsIOException{Stringres=response.body().string();UserResultresult=(UserResult)JsonUtils.fromJson(res,UserResult.class);if(result!=null&&result.getCode()==0&&result.getData()!=null){// UI 操作需切回主线程runOnUiThread(()->{...});}}});

4.2 本地数据库:SQLite 持久化

通过MySqliteOpenHelper管理 6 张数据表:

-- 用户表CREATETABLEuser(idINTEGERPRIMARYKEY,account,password,name,sex,phone,room,photo,userType);-- 请假记录表CREATETABLEleave(idINTEGERPRIMARYKEY,userId,note,date,statue,path);-- 新闻表(含已读/未读标记)CREATETABLEnews(idINTEGERPRIMARYKEY,title,content,date,path,new,read);-- 通知表CREATETABLEnotice(idINTEGERPRIMARYKEY,title,content,date);-- 管理员课程表CREATETABLEadminCourse(idINTEGERPRIMARYKEY,number,name,credits,type);-- 学生已选课程表CREATETABLEstudentCourse(idINTEGERPRIMARYKEY,userId,number,name,credits,type);

数据库初始化时预置了:

  • 两个默认管理员账号(admin/123,教学院长/123)
  • 3 条示例校园新闻(黄冈师范学院相关内容)
  • 2 条班级通知
  • 6 门示例课程(大学语文、大学美术、中国近代史等)

静态变量mUser作为全局当前用户缓存,登录成功后赋值,各 Activity/Fragment 直接读取。

4.3 主题换肤机制

基于Android-SkinSupport开源框架实现运行时换肤,分为三步:

第一步:Application 初始化

// MyApplication.javaSkinCompatManager.withoutActivity(this).addInflater(newSkinAppCompatViewInflater())// 基础控件拦截.addInflater(newSkinMaterialViewInflater())// Material Design 控件拦截.setSkinStatusBarColorEnable(false)// 关闭状态栏换肤.setSkinWindowBackgroundEnable(false)// 关闭 WindowBackground 换肤.loadSkin();

第二步:主题选择与保存

// ThemeActivity.java - Spinner 选择主题ArrayList<String>list=newArrayList<>();list.add("经典主题");// index 0list.add("养眼主题");// index 1list.add("流行主题");// index 2spinner.setOnItemSelectedListener(newOnItemSelectedListener(){@OverridepublicvoidonItemSelected(...){selectedType=position;SPUtils.put(activity,SPUtils.STUDENT_THEME,selectedType);// 持久化选择setTheme();// 应用主题}});

第三步:资源映射

三套主题通过不同的 drawable 资源实现视觉差异(如按钮背景btn_border_fill/btn_border_fill_1/btn_border_fill_2),换肤框架根据当前选中索引动态加载对应资源。这种方式无需重启 Activity 即可生效。

4.4 图片处理体系

项目构建了一套完整的图片处理流水线:

PictureSelector (选择) ↓ GlideEngine (加载引擎实现 PictureSelector 的 ImageEngine 接口) ├── loadImage() → 普通/网络图片加载 ├── loadFolderImage() → 相册目录缩略图(圆角 R=8dp) ├── loadGridImage() → 网格图片(200x200 centerCrop) ├── loadAsGifImage() → GIF 动图支持 └── 长图智能识别 → MediaUtils.isLongImg() 判断 ├─ 长图 → SubsamplingScaleImageView(支持缩放/双击) └─ 普通图 → ImageView ↓ Okhttp.uploadFile() (上传至服务端) → MultipartBody FORM 表单上传

关键设计点:

  • 长图自适应:通过判断宽高比自动切换到SubsamplingScaleImageView,支持双击缩放和手势拖拽,避免 OOM
  • 圆角缩略图:相册目录页使用RoundedBitmapDrawableFactory设置 8dp 圆角
  • 头像上传:请假申请时可附加图片证据,通过MultipartBody上传至服务端/file/upload接口

4.5 数据持久化:SPUtils 工具类

基于SharedPreferences封装的通用键值存储工具,管理以下持久化项:

Key类型用途
is_firstBoolean是否首次启动
user_typeInteger用户角色(0学生/1管理员/2院长)
user_idString当前登录账号
last_nameString上次输入的用户名(记住密码)
last_pswString上次输入的密码
auto_loginBoolean自动登录开关
remember_passwordBoolean记住密码开关
student_themeInteger当前主题索引

内部通过反射调用apply()方法实现异步提交,并做了兼容性降级(apply不可用时回退到commit)。


五、UI/UX 设计亮点

5.1 自定义导航栏

底部导航未使用BottomNavigationView,而是采用RadioGroup + RadioButton自定义方案:

  • 每个 RadioButton 通过setCompoundDrawables()设置图标(68x68 dp)
  • 使用 Selector 资源实现选中/未选中状态切换(颜色+图标变化)
  • 根据角色动态控制rbManege(学生管理)可见性

这种方案的灵活性在于可以完全控制图标大小、间距和样式,适合需要高度定制导航栏的场景。

5.2 欢迎页倒计时

OpenActivity实现 5 秒倒计时自动跳转,同时支持点击"跳过"立即进入:

CountDownTimertimer=newCountDownTimer(5000,1000){publicvoidonTick(longmillisUntilFinished){in.setText(millisUntilFinished/1000+"秒");}publicvoidonFinish(){finishView();// 时间到自动跳转}};

跳转前会检查自动登录状态:若之前勾选了自动登录且本地存有 userId,则静默验证并直接进入主页;否则进入登录页。

5.3 双击退出

MainActivity重写onKeyDown,监听返回键实现双击退出(间隔 < 2 秒):

publicvoidexit(){if(System.currentTimeMillis()-time>2000){time=System.currentTimeMillis();Toast.makeText(myActivity,"再点击一次退出应用程序",Toast.LENGTH_LONG).show();}else{finish();}}

5.4 登录安全增强

  • 图形验证码:每次进入LoginActivityonStart)随机生成 4 位字母数字验证码,纯客户端校验
  • 密码本地比对:先远程拉取用户信息,再在客户端做密码equalsIgnoreCase比较
  • 记住密码:通过 SPUtils 持久化上次登录凭据,复用 CheckBox 状态

六、项目结构与代码组织

6.1 包结构

com.example.campus/ ├── MyApplication.java # Application 入口(换肤初始化) ├── bean/ # 数据实体 │ ├── User / News / Leave / CourseSelection / StudentCourse │ └── *Result # 统一响应包装(code + data) ├── enums/ # 枚举定义 │ ├── UserTypeEnum # 用户角色 │ ├── ComeTypeEnum # 请假去向类型 │ └── RepairsStatusEnum # 报修状态 ├── util/ # 工具类 │ ├── Okhttp.java # 网络请求封装(单例) │ ├── SPUtils.java # SharedPreferences 封装 │ ├── MySqliteOpenHelper.java # 数据库管理 │ ├── JsonUtils.java # JSON 解析工具 │ ├── ConverterUtils.java # 类型转换工具 │ ├── GlideEngine.java # Glide 图片引擎 │ └── KeyBoardUtil.java # 键盘控制工具 ├── widget/ # 自定义控件 │ └── ActionBar.java # 统一标题栏组件 ├── adapter/ # RecyclerView 适配器 │ ├── NewsAdapter / NoticeAdapter │ ├── LeaveAdapter / CourseSelectionAdapter │ └── UserAdapter └── ui/ ├── activity/ # Activity 页面(32个) │ ├── BaseActivity.java # 基类 │ ├── OpenActivity / LoginActivity / RegisterActivity │ ├── MainActivity # 主框架(Fragment 容器) │ ├── ThemeActivity # 主题设置 │ ├── *News*Activity # 新闻相关(学生浏览 + 管理员管理) │ ├── *Notice*Activity # 通知相关 │ ├── *Leave*Activity # 请假相关 │ ├── *Selection*Activity # 选课相关 │ └── PersonActivity / PasswordActivity └── fragment/ # Fragment 内容页 ├── StudentHomeFragment # 学生首页 ├── AdminHomeFragment # 管理员首页 ├── UserFragment # 个人中心 └── UserManageFragment # 用户管理(管理员)

6.2 BaseActivity 基类

所有 Activity 继承自BaseActivity,统一处理公共逻辑(如换肤兼容、ActionBar 绑定等),保证各页面行为一致性。


七、总结与展望

7.1 技术亮点总结

维度实践效果
架构Activity + Fragment 主从结构 + 角色路由一套代码适配学生/管理员双角色
网络OkHttp 单例封装 + 异步回调统一接口风格,超时可控
存储SQLite 本地持久化 + SharedPreferences 配置存储离线可用 + 用户偏好保留
换肤Android-SkinSupport 运行时换肤无需重启即时生效
图片PictureSelector + Glide + 长图智能识别全链路图片处理能力
体验欢迎倒计时 / 双击退出 / 记住密码 / 自动登录符合移动端交互习惯

7.2 可优化方向

  1. 网络层升级:可引入 Retrofit + RxJava(依赖已声明)实现更优雅的链式调用和线程切换;考虑添加拦截器统一处理 Token、日志、错误码
  2. 架构现代化:迁移至 Jetpack Component(ViewModel + LiveData / Navigation Component),替代手动 Fragment 管理和show/hide 模式
  3. 数据库 ORM:引入 Room 替代原生 SQLiteOpenHelper,获得编译期 SQL 检查、LiveData 观察等能力
  4. 模块化拆分:按功能域(news / notice / course / leave)拆分为独立模块,降低耦合度
  5. 图片缓存策略:结合 Glide 磁盘缓存与服务端 CDN,优化图片加载性能
  6. 安全加固:密码传输加密(HTTPS)、Token 机制替代明文密码比对、服务端验证码替代客户端生成

7.3 适用场景

本项目的技术方案适用于以下类型的中小型 Android 应用开发:

  • 企业/校园内部管理工具
  • 多角色权限的信息展示平台
  • 以列表浏览 + 表单提交为主的应用
  • 需要主题定制能力的 C 端产品

本文基于 campusInfoApp 项目源码撰写,截图来源于应用实际运行效果。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 6:45:18

C++函数模板:从泛型编程到编译时多态的实战指南

1. 项目概述&#xff1a;为什么我们需要模板&#xff1f;如果你写过C&#xff0c;肯定遇到过这样的场景&#xff1a;你需要一个函数来比较两个整数的大小&#xff0c;于是你写了一个max(int a, int b)。过一会儿&#xff0c;你又需要比较两个浮点数&#xff0c;于是你复制粘贴代…

作者头像 李华
网站建设 2026/8/23 6:44:06

360CDN发布HTTP/3(QUIC)弱网加速方案:实测首屏提速40%,彻底终结移动端接口超时与频繁断连

2026年8月21日&#xff0c;针对移动端用户在地铁、高铁、电梯等弱网环境下频繁遭遇的小程序接口超时、APP加载卡顿及网络切换断连等痛点&#xff0c;国内领先的云安全服务商360CDN正式推出“HTTP/3(QUIC)弱网加速解决方案”。该方案依托基于UDP底层的新一代传输协议与全球边缘节…

作者头像 李华
网站建设 2026/8/23 6:42:55

【Linux】 编译与动静态库相关

目录 前言 Part1. GCC四个编译阶段 Part1.1. 预处理 Part1.2. 编译 Part1.3. 汇编 Part2. 静态库与动态库 Part2.1. 动态库 Part2.2. 静态库 Part2.3. gcc静态链接参数 Part3. 条件编译 Part4. /etc/sudoers 权限配置 Part5. 目标文件 .o Part6. Make与Makefile P…

作者头像 李华
网站建设 2026/8/23 6:36:43

MCP供应链攻击:filesystem-pro-plus 投毒事件技术复盘

Hi&#xff0c;老友们&#xff0c;好久不见&#xff0c;我开始继续活跃于CSDN了。欢迎继续支持我的文章&#xff01; 谢谢&#xff5e; 如果你今天在生产环境中运行代理&#xff0c;请阅读此内容。 如果你本周从公共注册表拉取了 MCP 服务器且没有进行审计&#xff0c;请阅读…

作者头像 李华
网站建设 2026/8/23 6:35:33

基于微信小程序与SpringBoot的攻略交流平台全栈开发实战

你有没有过这样的经历——打开一个旅游App&#xff0c;想找某个景点的真实攻略&#xff0c;结果满屏都是官方宣传图、千篇一律的“必去打卡点”和夹杂着广告的游记&#xff1f;或者&#xff0c;当你费尽心思完成了一个功能齐全的毕业设计&#xff0c;却因为选题太普通、文档不清…

作者头像 李华
网站建设 2026/8/23 6:34:53

强烈反对买入机器人股票

人形机器人根本没有市场。你告诉我哪个地方需要&#xff1f;想解套&#xff1f;过几天可能都倒闭了。

作者头像 李华