WakeUp课程表项目指南

写在前面

大学生活一下子就过去两年了,在这里也小小地感慨一下,时间过得好快哦。最近心情比较复杂,所以大学生活究竟过得怎么样,先不予置评。就像《岁月如歌》说的那样:

天气不似如期
但要走 总要飞

生活总是要继续的,生活中也还有很多我所珍视的东西。WakeUp课程表作为自己首个独立作品,看着它从最原先的简陋,到现在基本功能还是都有了,且界面还是差强人意的,我还是有点成就感的。我不知道自己还能对它维护多久,可能到大三也就不更了?看心情吧,当然也希望有人能接下这个工作。所以就写下这篇东西。查看项目点这里。如果你还不知道这个App长什么样,可以在主流的应用商店搜索“WakeUp课程”,或者点击这里

负责任地说,其实入门Android并不需要掌握全部的Java特性,我当时也算是一边写Android一边加深对Java的理解(其实到现在也还是在高级特性边缘试探?)现在Google宣布Kotlin成为Android官方开发语言,Kotlin看起来会简洁很多。也一直想用Kotlin重构项目,还是看心情吧😶瞬间感觉自己很佛系了。

废话就不多说了,还是推荐两本书吧,《Java编程思想》和《第一行代码:Android(第2版)》,两本都比较厚,后面那本很适合Android入门。

这篇文章不是教你怎么进行Android开发,只是让你知道如果想修改某个功能应该去哪里找。下面的内容如果暂时没看懂没关系,可以慢慢来。我会在其中穿插一些开发知识来帮助理解;如果是大佬在阅读过程中觉得项目架构有问题(我自认为是有问题的),恳请指出。右边有一个目录,可以快速跳转到自己需要看的位置。

项目总览

项目总览

如果你没有安装Android Studio,这个目录结构跟你在文件夹里看到的是不太一样的,真实的文件夹包裹得有点深,不过相信聪明的你多点几下就能有所发现。下面按照这个结构来介绍各部分的大致内容。

manifest

这个文件夹下的AndroidManifest.xml是一般Android项目都有的一个配置文件,是一个文本文件,可以用任何的文本编辑器打开。

下面的内容是声明了App需要用到的权限,第一项是互联网访问的权限,第二项是存储空间写的权限。互联网访问的权限一旦声明,App就可以访问网络连接的;Android有一些是敏感权限,比如这里的存储空间读写权限,在Android 5.0之后除了在这里声明,还需要动态去申请权限。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

下面这个部分是由application标签包裹的代码块,实际上比较长。android:icon指明了App的图标,android:label指明了App的显示名称。省略号部分就是注册了各种activity、service等组件,这方面可以去自行搜索“Android四大基本组件”,此处就不展开了。

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        ……
        
</application>

java

所有的Java代码都集中在这个文件夹里面了,这里你会看到它有三个子文件夹,这是新建项目自动生成的,一般看第一个,其它两个跟测试相关(我也没用过)。

com.suda.yzune.wakeupschedule

其实java下面的三个子文件夹都叫上面这个名字,后面两个在后面会有(test)等标注。这个长长的名字叫应用包名,用于来唯一标识Android应用。可以看到这里又有很多子文件夹,这些文件夹都是我手动创建的,是为了分类然后便于查看,这个分类不是很细致,有点马虎的,但是还是能很快定位到自己要查看的代码。

adapter

adapter

这些Adapter都是ListView、RecyclerView或者ViewPager的Adapter(好像说得有点废……)。

  • ClassTimeAdapter是关联了设置页面-上课时间里面,那个选择第几节是什么时候开始的RecyclerView。
  • OtherCourseAdapter是关联了侧栏-我要蹭课里面可蹭课程的列表。
  • SchedulePagerAdapter这个添加的时间不长,是为了做主界面左右滑动切换周数加的,关联了主界面那个ViewPager。
  • TodayCourseAdapter是关联了侧栏-今日课程里面的课程列表。

model.bean

model.bean

这里主要存放了一些自己定义的数据类:

  • AppWidgetBean:用于管理桌面小部件的数据类,也是和数据库GreenDao中表字段对应的数据类,记录了小部件的id和类型(日视图为0,周视图为1)。
  • Course:课程表最核心的数据类,课程表主界面看到的一个色块对应就是一个Course对象。
  • UpdateInfo:更新信息的数据类,每次检查更新时都会把服务器返回的数据解析成这种对象。

后面两种数据类一般都是搭配Gson来使用的,也就是用Gson对象把它们对应的对象生成json字符串,或者是用Gson对象把相应的json字符串解析成相应的对象。

下面说明一下Course类:

public class Course {
    private String name, room, teach, id, campus;//课程名称、上课教室、授课老师
    //这个id是用来存放手动调整颜色的编号的、campus是用来标记苏大校区的
    int start, step, day, startWeek, endWeek, isOdd;
    //开始上课节次、课程的长度(比如两节课就为2)
    //day是指星期几(周一day的值为1)
    //isOdd用来标记单双周(0为全周,1为单周,2为双周)
    long num;
    ……
}

service

service

这个service就是用来放后台服务代码的,而且都是关于桌面小部件的更新服务。

  • ListViewService:负责每日课程小部件中列表的更新。
  • ScheduleWidgetService:负责周视图小部件中课程的更新。

utils

utils

集中存放工具类,不过有点杂乱。诶……感觉如果要解释可以新写一篇博文了。这里就简单说一说好了。

  • BaseDao、DaoManager、DaoUtils、WidgetDaoManager:对GreenDao封装的工具类,在小部件相关的代码可以看到它们的身影。我是很迟才在项目中引入了数据库这个工具,同类的App好像一开始就是用数据库来储存课程信息的,羞愧羞愧。
  • Config:目前这个工具类没有用,里面放的是语音识别服务的密钥之类的,之前想做一个语音输入课表的功能,奈何识别准确率太低。
  • Constants:里面放了一些常量,比如教务系统网址、验证码网址,还有检查更新的地址等。
  • CourseUtils:跟课程处理有关的工具类,但是里面放的东西比较杂。makeCourseTogether这个函数是针对从苏大教务获取的课程分节的情况的,让相同的连续的课程结合在一起;post这个函数是将苏大课程传回服务器的;showCampusChoose用来显示对话框来让苏大学生选择所在校区;calAfterTime用来计算下课时间。
  • DisplayUtil:跟显示相关的工具类,里面有几个常用的单位转换函数,比如dp转换成px。
  • DonateUtils:跟捐赠有关的工具类,里面是有冗余代码的,有用的是isAppInstalled这个函数,用来检测某个App是否安装了,我用来检测支付宝是否安装了。
  • GlideAppEngine:这个是为了让知乎开源的图片选择库兼容Glide新版本,而继承的一个类。
  • JsonUtils:只是用来检测Json是否合法的工具类,运用在侧栏-恢复那里。
  • MyCookieJar:模拟登陆时需要的……可以不用管。
  • MyRadioGroup:其实这个不应该放在工具集合这里,这是自定义的单选按钮组,修改课程颜色的时候你会看到它,原生的RadioGroup不能分行。
  • OkHttpUtil:这个是很重要的封装了OkHttp的工具类,主要用于模拟登陆教务系统。
  • SharePreferencesUtils:这个类可以很方便地将int、String、boolean等数据通过SharePreferences储存起来,也可以取出来。因为项目中大量用到了SharePreferences,课程信息和设置都是通过这个储存起来的😂
  • UpdateUtil:检查更新的代码在里面。
  • ViewUtil:里面只有一个函数,就是取消activity的toolbar以及使其顶栏沉浸。

啊,这部分终于粗略地介绍完了。

view

view

接下来是这个view了,顾名思义,view就是我们能够看到的视图部分,所以这里面放的都是直接负责App界面操作的代码,当然后面还会说到它们对应的布局代码。

  • AboutActivity:点击 侧栏-关于 出现的界面,里面的内容除了App版本号以外,其他部分都是固定的,版本号会随着工程文件的变化而变化。
  • DecodeActivity:这个我没有把入口暴露出来,它是一个解析苏大教务课程HTML的界面,大体上就是把网页源码复制到上面,就可以生成课程表。
  • DonateActivity:捐赠页面,如果想把捐赠的支付宝账号改成自己的,修改里面的qrcode_url即可。
  • FixActivity:电脑义修页面,核心函数是startQQChat,会根据里面的参数发起QQ聊天。
  • IntroActivity:如果是一路升级过来的朋友应该不会看到这个页面,这个是寒假的时候加入的引导页。里面使用了一个第三方开源库,关于项目中开源库的使用会在下文集中说明。
  • LoginXKActivity:刚开始课程表登录苏大教务是用网页形式登录的,不太友好。而这个是那个友好的登录页面。模拟登录、HTML解析的代码都在这里,把一个activity写得这样“胖”是不太好的,这里我确实没有把模块分离好。尤其是HTML的解析代码其实在项目中复制着用了好几次,这个完全可以封装成一个工具类的。
  • MainActivity:这个就是我们一开始的网页登录界面,里面有一个WebView。然后课程解析部分的代码跟上面的是重复了的。我的建议是,除非你有十足的把握,不然还是不要改动,因为这里涉及到了Java对JavaScript的调用。这个页面保留着,是因为少数人用上面的界面登录会遇到验证码一直错误的问题,如果错误次数多了,就会开放这个页面的入口,用网页的形式进行登录。
  • ScheduleActivity:这个就是日常我们见到的主界面。在之前,它负责了课程的显示,还有侧栏也是依托在这里的;现在,在主界面支持左右滑动切换每周课程后,它不再直接负责课程的显示,而是在刷新界面时计算当前周数。当我们介绍到它对应的布局时,你应该会更加清晰一点。
  • SettingsActivity:设置界面,在这里你会看到SharePreferencesUtils工具类的频繁使用,因为这些设置的参数都是以SharePreferences的形式保存的。
  • ShareActivity:侧栏-分享/备份的界面,里面有个函数对系统剪贴板进行操作,里面也能找到属性动画的运用例子。
  • ThemeSettingsActivity:侧栏-自定风格的界面,部分设置项跟SettingsActivity有重复。里面本来有一个主界面背景模糊程度的调节功能,但是我测试起来有点小问题,就是设置后会有模糊效果,但是这个模糊效果不随设置的数字改变而改变。
  • TimeSettingActivity:设置-设置上课时间的界面,里面有个RecyclerView,上面在说Adapter的时候有提到。
  • TodayCourseActivity:今日课程的界面,我个人感觉这个比较少人打开……
  • ViewOtherCourse:蹭课的界面,我发现 你好苏大 是有蹭课接口的,到时候可以研究研究。

上面的都是activity,下面介绍一下fragment。每个fragment都是依赖于上面的某个activity的。

  • Intro1Fragment、Intro2Fragment、Intro3Fragment:配合IntroActivity使用的,对应三个引导界面。有部分设置现在是放到引导界面去设置的,比如在第二个引导界面设置是苏大的还是其他大学的。这三个界面不算得很精致,如果可以的话要重新设计一下。
  • ScheduleFragment:配合ScheduleActivity使用。ScheduleActivity在初始化时会新建25个ScheduleFragment对象,对应25个周,由于Android的回收机制,这个对性能的影响不太大的。目前发现的问题是旋转屏幕时界面会空白,这可能跟Fragment的生命周期有关。

还会看到下面还有ScheduleWidget和TodayWidget,对应两种桌面小部件。我个人感觉目前网上关于AppWidget的资料都是翻译了一下官方文档,或者是太旧了,反正怎么都不太符合业务需求。我会考虑写一篇单独介绍AppWidget的文章。

MyAppGlideModule

MyAppGlideModule

你也许会注意到这个虽然在java文件夹下,但是也不属于上面的任何一个子文件夹。这个是为了解决Glide这个图片加载库新旧版的兼容性问题,不能删除。

res

res

终于把java这个文件夹介绍完了。现在轮到res了,这是resource的简写,里面主要存放的是项目的资源文件,包括xml文件、图片等。

anim

anim

这是存放动画xml文件的文件夹,logo_jump.xml是第一个引导页面的小鹿飞跃动画效果的控制文件。

drawable

这个文件夹里是各种图片资源,文件实在太多了截图截不过来,各个文件分别是什么用途,可以打开下面的布局文件去查看。一般来说,App的体积大小主要取决于资源文件的大小。加入新的图片时应该注意适当压缩一下图片,在质量和大小之间把握平衡。还有要注意命名要有规律,有规律的命名可以让自己一看就知道这个资源是用在哪里的(我这里的命名也不是特别规范,因人而异)。

layout

layout

这里就是布局文件了,绝对要比上面的Java代码要有意思,因为在Android Studio中,这些布局文件都是可视化的,下面是一个例子:

例1

这是我们的登录界面,中间部分的代码改动会在右边的可视化界面体现出来。不过右边的可视化界面并不是100%还原的,比如我们实际运行时看到的登录界面是没有粉红色的工具栏的。借助这个基本实时的可视化界面,你可以自由地修改我们现有的界面。

看到中间界面左上角那个C按钮了吗?点击它就可以跳转到对应界面的Java代码。同样,在Java代码显示区的左上角,也有一个跳转到布局文件的按钮,可以很方便地来回切换。布局文件和Java代码一起看,会加深你对其功能的理解。

menu

menu

这个是用来放菜单的,而里面只有一个文件,这个是关于侧栏菜单内容的文件。当你点开它时,它是下面这样一个界面:

例2

这跟上面的可视化界面不太一样,但是不影响你去修改它。可以看到,一个item对应一个菜单的选项,可以指定它的id、图标和标题。

mimap

mipmap

这里放的是App启动图标,ic_launcher.png就是App的启动图标,有很多个不同尺寸的版本。fix_launcher.png和today_launcher.png是shortcuts中显示的两个图标,shortcuts不是所有ROM都支持的,你可以尝试一下长按课程表App的启动图标,看看有没有shortcuts出现。

values

values

这里放着一些资源常量,比如颜色、字符串、styles等等。在写这个项目的时候没有考虑过项目国际化的问题……所以无论你的系统是什么语言,App都只有简体中文。如果要做项目国际化的话,需要在strings.xml定义。嗯……工作量是有点大的。

xml

xml

这里是一些配置文件而不是资源文件。其中:

  • schedule_widget_info.xml和today_widget_info.xml都是桌面小部件的配置文件,配置了小部件的更新频率、初始化尺寸等信息。桌面小部件会另开一篇来写。
  • shortcuts.xml是shortcuts的配置文件,是静态的。一般来说静态的也够用了,感觉shortcuts这个功能并没有普及开来……

项目总配置

Gradle Scripts

Gradle Scripts里面是项目总体的配置,一般来说只需要修改两个文件,其他文件最好不要修改。

上面说的两个文件它们的实际名字都是一样的,都是build.gradle,不过实际存放在不同的文件夹里,作用也不太一样。

  • build.gradle(Project:……)这个一般在添加第三方库的时候需要配置一下。
  • build.gradle(Module:app)这个可以修改的地方就很多了,下面举些例子。
minSdkVersion 21
targetSdkVersion 27
versionCode 19
versionName "2.10"

上面这段中:

  • minSdkVersion是项目最低sdk的版本,决定了你的应用最低可以安装在哪个Android版本上,这里的21是指Android 5.0,也就意味着Android 4.4上无法安装这个App。一般来说要兼容更低的Android版本会增加你的工作量。
  • targetSdkVersion是项目的目标sdk版本,如果你要用到新平台的新特性,就需要修改这里。
  • versionCode后面是一个数字,用来表示版本更迭,每一次推出正式的更新是都应该增加这个数字。
  • versionName后面跟的是一个字符串,其实也不一定要是数字字符串,可以弄一些好玩的,每个版本之前有区分度就行。
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.android.support:appcompat-v7:27.0.2'
    compile 'com.android.support:support-v4:27.0.2'
    compile 'com.android.support:design:27.0.2'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'com.android.support:cardview-v7:27.0.2'
    compile 'com.github.apl-devs:appintro:v4.2.2'
    compile 'com.github.GrenderG:Toasty:1.2.8'
    compile 'com.tapadoo.android:alerter:2.0.0'
    compile 'com.zhihu.android:matisse:0.4.3'
    compile 'com.github.bumptech.glide:glide:4.6.1'
    compile 'com.github.florent37:glidepalette:2.1.2'
    compile 'jp.wasabeef:glide-transformations:3.1.0'
    compile 'org.greenrobot:greendao:3.2.2'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
    testCompile 'junit:junit:4.12'
}

上面这一段是我们用来添加第三方库的,下面会介绍项目中第三方库的使用情况。

第三方库的使用情况

support库

上面以com.android.support开头的就是support库,这些support库可以使App在各个版本保持同样的用户体验,比如在Android 5.0以下系统使用Material Design。如果想对它了解更多,可以参考这篇文章:Android Support Library的前世今生

OkHttp库

OkHttp是具有高效的请求效率的网络请求库,项目中把其进行再次封装成为一个工具库。学习网络请求方面的知识,可以参考:OkHttp使用完全教程

Gson库

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常见于网络数据的传送。在项目中不仅用于网络数据的传送,还将其用于信息的本地存储。而Gson,是一个Google的一个解析和生成Json的开源库。可以参考:你真的会用Gson吗?Gson使用指南

AppIntro库

AppIntro库可以让你快速生成美观的引导界面,GitHub地址在这里,里面有开发者写的使用文档,能满足一般使用。

[站外图片上传中...(image-783b74-1523195636642)]

Toasty库

Toasty库是用来代替系统自带的Toast通知的,Toasty的样式更加多,还允许很方便地自定义样式,GitHub地址在这里,里面有开发者写的使用文档,能满足一般使用。

Toasty库

Alerter库

Alerter库在项目中用作用户操作的提醒,很有动感,比较醒目,GitHub地址在这里,里面有开发者写的使用文档,能满足一般使用。

[站外图片上传中...(image-e89646-1523195636642)]

matisse库

matisse是知乎开源、界面优美的图片/视频选择库,可以自定义主题,以及定义一些过滤规则等,而且集成起来还是很方便的。项目GitHub地址在这里,里面有使用文档,能满足一般使用。

[站外图片上传中...(image-6ec6f4-1523195636642)]

[站外图片上传中...(image-3031e9-1523195636642)]

Glide库

Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide给我的感觉是很强大的,在网上的教程也非常多。GitHub地址在这里,然后这里有一份中文文档

[站外图片上传中...(image-a2a40a-1523195636642)]

GlidePalette库

GlidePalette是一个配合Glide使用的取色库,可以提取图片中明亮、鲜艳、主要等颜色,最多有6种取色方案,可以令图片很好地与环境融合。项目GitHub地址在这里,里面有使用文档,能满足一般使用。

[站外图片上传中...(image-a9eb28-1523195636642)]

glide-transformations库

glide-transformations是一个配合Glide使用的变换库,可以将在显示时变换图片,比如高斯模糊、或者黑白化、或者让图片圆形显示。项目GitHub地址在这里,里面有使用文档,能满足一般使用。

greenDAO库

greenDAO是一款开源的面向Android的轻便、快捷的ORM框架,将 Java对象映射到SQLite数据库中,我们操作数据库的时候,不在需要编写复杂的SQL语句,在性能方面,greenDAO针对Android进行了高度优化,最小的内存开销、依赖体积小同时还支持数据库加密。项目GitHub地址在这里,这个库个人感觉需要阅读多几篇教程才行,自己搜索丰衣足食哦。

好啦,以上就是第三方库的使用情况,我也是做过很对比才决定使用它们的,它们也没有让我失望啦。当然它们能够发挥更为出彩的,前提是要了解得更为深入。

结语

如果你看到了这里,非常感谢你的耐心,这篇只是初略地讲了一下项目目前的大体情况,可能在你看来没有什么干货。做这个项目我还是收获了很多的,不过整理起来都需要时间。码一篇博文还是蛮累的,还是贵在坚持吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容