胖葵音乐

胖葵音乐(Android 云音乐app)

运行效果

登录注册:

胖葵音乐

打开专辑,播放音乐,暂停播放,切换音乐

胖葵音乐

通知栏,通知栏进入app

胖葵音乐

修改密码

胖葵音乐

退出登录

胖葵音乐

开发工具

Android Studio 4.1.0

AndroidUtilCode主工具类模块:utilcode

glideTranformtions框架:CircleImageView

Realm数据库

项目整体框架说明

胖葵音乐

各个文件说明

这里简要概括,具体在代码里有注释说明

胖葵音乐

activity

1、专辑列表

2、基础通用部分,可供其他activity继承,避免重复啰嗦

3、修改密码界面

4、登录界面

5、主界面

6、个人中心页面

7、音乐播放页面

8、注册界面

9、欢迎界面

胖葵音乐

adapter

1、音乐专辑适配器

2、音乐列表适配器

胖葵音乐

constants

1、SharedPreferences常量

胖葵音乐

helps

1、音乐播放器相关方法

2、Realm数据库相关方法

3、用户相关方法

胖葵音乐

migration

1、数据迁移

胖葵音乐

models

1、专辑模型

2、音乐模型

3、音乐资源模型

4、用户模型

胖葵音乐

services

1、音乐服务

胖葵音乐

utils

1、资源数据读取

2、SharedPreference用户标记

3、用户功能

胖葵音乐

views

1、专辑间距离

2、输入框基本形式

3、音乐播放视图(含光盘、指针动画)

4、设置图片宽高相等

胖葵音乐

myapplication

1、完成一些依赖工具的初始化

胖葵音乐

anim

1、2、3、4、页面切换动画

5、光盘旋转动画

6、7、光盘指针动画

胖葵音乐

drawable

1、2、3、按钮点击高亮显示

4、5、8、文本点击高亮显示

胖葵音乐

layout

1、专辑列表

2、修改密码

3、登录

4、主页面

5、个人中心

6、音乐播放页基础布局

7、注册

8、欢迎

9、输入框

10、专辑基础布局

11、音乐基础布局

12、顶部导航栏

13、音乐播放页面动画布局

胖葵音乐

values

1、输入框样式

3、尺寸

4、常数

一些总结

下面总结一些项目中用到的比较重要的点,其他的请大家结合代码注释看吧。

AndroidUtilCode工具类

我们这里调用方法来判断手机号是否有效,使用如下:

if(!RegexUtils.isMobileExact(phone)){
    Toast.makeText(context, "手机号无效", Toast.LENGTH_SHORT).show();

}

任务和返回栈(Task栈)

任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。一般情况下我们可以认为一个应用就是一个任务,并且这个应用启动的所有Activity会按照打开的顺序放入堆栈中即是这个任务对应的返回栈。

默认情况下,一个应用对应一个任务对应一个返回栈。如果应用之前没有被启动过,点击主屏幕应用启动器中的图标的时候会生成一个全新的任务,并且该应用的“主”Activity 将作为任务返回栈中的根 Activity 打开,之后依次打开的Activity会按照打开的顺序压入返回栈中。当按”BACK”键返回时,这些压入返回栈中的Activity会按照“后进先出”的原则依次出栈,恢复回退栈中前一个 Activity 的执行。

由此可知,当我们要实现退出登录的功能时,如果只是单纯的跳转到登录界面,那么当用户点返回键时,就会再回到个人中心页面。显然这是不合逻辑的,我们需要用户退出登陆后回到登录页面,并且点返回键会直接退出app。这就需要用到intent标志符。

Intent.FLAG_ACTIVITY_CLEAR_TASK 清除当前TASK栈中的Activity

Intent.FLAG_ACTIVITY_NEW_TASK 新建一个TASK栈

这样处理之后,栈中就只剩下我们新打开的登录页面一个Activity,这时候再按返回键就会直接退出app了。

实现如下:

Intent intent = new Intent(context, LoginActivity.class);
//添加 intent标识符,清理 task栈,并且新生成一个 task栈
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

recyclerview及其分割线

https://blog.csdn.net/lmj623565791/article/details/45059587

LayoutInflater

在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。

具体作用:

1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;

2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。

LayoutInflater 是一个抽象类,在文档中如下声明:

public abstract class LayoutInflater extends Object

获得 LayoutInflater 实例的三种方式

  1. LayoutInflater inflater = getLayoutInflater();//调用Activity的getLayoutInflater()

  2. LayoutInflater inflater = LayoutInflater.from(context);

  3. LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

更多内容请看:https://www.cnblogs.com/top5/archive/2012/05/04/2482328.html

onMeasure

View在屏幕上显示出来要先经过measure(计算)和layout(布局)

当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,“你想要用多大地方啊?”,然后传入两个参数——widthMeasureSpec和heightMeasureSpec.
这两个参数指明控件可获得的空间以及关于这个空间描述的元数据.
更好的方法是你传递View的高度和宽度到setMeasuredDimension方法里,这样可以直接告诉父控件,需要多大地方放置子控件.

更多内容请看:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html

glideTranformtions框架

加载网络图片,用法如下:
  /**
    * 加载网络图片
    * 基本形式 先with(),再load(),最后into()
    */
    mImage = (ImageView)findViewById(R.id.image);
    Glide.with(this)
        .load("https://s0.52poke.wiki/wiki/thumb/4/4f/120Staryu.png/300px-120Staryu.png")
        .into(mImage);
CircleImageView

圆角 ImageView,用于显示光盘圆图

更多内容请看:https://www.cnblogs.com/WUXIAOCHANG/p/10667210.html

interpolator

Interpolator负责控制动画变化的速率,使得基本的动画效果能够以匀速、加速、减速、抛物线速率等各种速率变化。
动画是开发者给定开始和结束的“关键帧”,其变化的“中间帧”是有系统计算决定然后播放出来。因此,动画的每一帧都将在开始和结束之间的特定时间显示。此时动画时间被转换为时间索引,则动画时间轴上的每个点都可以转换成0.0到1.0之间的一个浮点数。然后再将该值用于计算该对象的属性变换。在变换的情况下,y轴上,0.0对应于起始位置,1.0对应于结束位置,0.5对应于起始和结束之间的中间,对于一些插值器其值还可以是0~1之外的数值。

MediaPlayer

Android的MediaPlayer包含了Audio和Video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlaer来实现的。

更多内容请看:https://www.cnblogs.com/senior-engineer/p/7867626.html

Realm数据库

Realm数据库是一个非常轻量级的数据库,相比于sqlite,它的存储速度更快。

Realm数据库通过将Java对象直接保存到磁盘作为对象,而不是首先将它们映射到其他数据类型(如SQLite)来工作。在Realm数据库的中心,这个叫Realm的东西,这相当于一个传统的数据库。Realm可以将不同类型的对象映射到磁盘上的一个文件。另一种查看方式是,Realm是不需要从Java对象到磁盘上持久版本的单独映射的数据库。

它是一种像你所看到的是什么保存的工作流程 - 如果对象是Realm管理对象,则用户界面中对象的更改将自动保存到数据库。Realm管理的对象与SQLite表相当。要使Java对象成为Realm管理,该类必须扩展RealmObject或实现RealmModel接口。

更多内容请看:https://blog.csdn.net/jxq1994/article/details/75670295

MD5加密

在网络中传输明文是一件非常危险的事情,所以通常将密码加密后传至服务器,由服务器保存密文在登录判定时只需比较密文是否相同即可。

MD5加密是一种常用的加密算法,全称为“Message-Digest Algorithm 5”,即消息摘要算法,由MD2、MD3、MD4演变过来的,是一种单向加密算法,是一种不可逆的加密方式。

MD5优点:

  • 压缩性:任意长度的数据,算出的MD5值长度都是固定的。
  • 容易计算:从原数据计算出MD5值很容易。
  • 抗修改性:对原数据进行任何改动,所得到的MD5值都有很大区别。
  • 强抗碰撞:已知原数据和其MD5值,想找到一个相同MD5值得数据是非常困难的。

我们引入Realm数据库,进行MD5加密实现如下:

RealmHelp realmHelp = new RealmHelp();
boolean result = realmHelp.validataUser(phone,EncryptUtils.encryptMD5ToString(password));

我们查看数据库内容,可以看到存储的加密密码如下:

胖葵音乐

SharedPreferences

SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。
其中的原理是通过Android系统生成一个xml文件保到:/data/data/包名/shared_prefs目录下,类似键值对的方式来存储数据。
Sharedpreferences提供了常规的数据类型保存接口比如:int、long、boolean、String、Float、Set和Map这些数据类型。

我们的应用如下:

1、用户登录

(1)新账号第一次登录时,利用SharedPreferences保存登录用户的用户标记(在这里就是手机号)

​ (2)用全局单例类UserHelp保存登录用户信息

​ <1>用户登录之后

​ <2>用户打开应用程序,检测SharedPreferences中是否存在登录用户标记,如果存在则给UserHelp赋值,并进入主页,否则进入登录页面

2、用户退出登录

删除SharedPreferences保存的用户标记,退出到登录页面

实现如下:

//保存用户登录标记
boolean isSaved = SharedPreferencesUtils.saveUser(context,phone);
//删除SP保存的用户标记
boolean isRemove = SharedPreferencesUtils.removeUser(context);

数据库迁移(升级)

使用Realm时,设定好model类,直接使用Realm.getDefaultInstance()就可以直接创建跟model类相对应的表格。但有时候需要更新表格或添加或减少表格,就要更新model类了。但直接更新model类是不行的,会报错,要进行migrate迁移操作才能成功更新图表。

实现如下:

/*
* Realm数据库发生结构性变化(模型或模型中的字段发生了增删改)时
* 需要对数据库进行数据迁移(升级)
*/
private static RealmConfiguration getRealmConf(){
    return new RealmConfiguration.Builder()
            .schemaVersion(1)
            .migration(new Migration())
            .build();
}

更多内容请看:https://blog.csdn.net/amberoot/article/details/94615346

完整项目链接

github:https://github.com/guyuanjunxi/PKmusic

移操作才能成功更新图表。

实现如下:

/*
* Realm数据库发生结构性变化(模型或模型中的字段发生了增删改)时
* 需要对数据库进行数据迁移(升级)
*/
private static RealmConfiguration getRealmConf(){
    return new RealmConfiguration.Builder()
            .schemaVersion(1)
            .migration(new Migration())
            .build();
}

更多内容请看:https://blog.csdn.net/amberoot/article/details/94615346

完整项目链接

github:https://github.com/guyuanjunxi/PKmusic

csdn:

上一篇:System Center Configuration Manager 2016 域准备篇(Part3)


下一篇:Java_IO流总结