专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
郭霖  ·  从零实现一个 KMP 插桩框架: EzHook ·  3 天前  
郭霖  ·  Android Studio 中的 ... ·  4 天前  
鸿洋  ·  画了10张图,带你搞定RecyclerVie ... ·  4 天前  
鸿洋  ·  掌握这17张图,掌握RecyclerView ... ·  6 天前  
51好读  ›  专栏  ›  鸿洋

教你如何实现 Splash 页面三秒跳转和动态下载最新背景图

鸿洋  · 公众号  · android  · 2017-06-21 07:31

正文

本文作者


本文由我姓王叫叔叔授权发布。

我姓王叫叔叔的博客地址:

http://www.jianshu.com/p/b38ec0bfee7d


最近公司产品大大说我们需要一个动态替换的闪屏页面,like 某猫,某东一样,可以动态替换。
产品大大就是厉害,说一句话我们就需要实现好几个功能:


  1. 创建一个冷启动后的闪屏页面(Splash 页面)

  2. 这个页面默认 3s 倒计时,点击倒计时按钮可以跳转并结束倒计时

  3. 点击图片如果有外链,则跳转应用的 web 页面用来作为活动页面(没错这点和某猫很像)

  4. 动态替换厉害了,我们需要在进入这个页面后去后台请求一下是否有新的图片,如果是新的图片则下载到本地,替换掉原来的图片,下次用户在进入 Splash 就会看到一个崭新的图片。


效果图




1

布局实现



布局文件文件相对来说还是比较简单,就需要一个 ImageView 和 Button 即可,Button 的背景是一个自定义的 shape,透明度颜色啥的,根据UI妹砸说的算就好了。



2

倒计时功能实现


实现倒计时的功能方法有很多,最基本的你可以使用 Handler 来实现吧,还可以是用 Timer 吧。


但是由于之前写验证码倒计时的时候发现 android.os 中有一个神奇的类叫 CountDownTimer 的类,此类神奇之处就在于你完全不需要理会那些线程交互他都给你处理好了,你只管在回调中处理时间设置跳转逻辑就好了。


但是有一个不足的地方就它的第一秒的倒计时有时候会不可见,所以我们将倒计时总时间设置为 4s 。



最后需要在有闪屏页面的情况下,进入开启倒计时:


private void startClock() {
    mSpJumpBtn.setVisibility(View.VISIBLE);
    countDownTimer.start();
}


3

下载功能实现点击跳转功能实现


上边说了我们 APP 点击图片需要可以跳转,下面代码给出了背景点击跳转的逻辑:



跳转逻辑可以根据实际的项目需求来规定,下面的代码中 Splash 为本地序列化的 model 用来存储网络下载的闪屏页面信息,稍后会有详细的序列化过程,此刻我们只需要关注跳转逻辑:



机智的你可能看出来我们并没有在离开页面的时候结束掉 timer,其实我们是复写了 onDestroy 方法。


@Override
protected void onDestroy() {
    super.onDestroy();
    if (countDownTimer != null)
        countDownTimer.cancel();
}


其实跳转以后还有一个坑就是,从 web 页面返回的时候,因为闪屏页面是你应用的第一个页面,而跳转到 web 页面的是你 finish 掉了该页面,那么从 web 页返回的时候不做处理,用户就直接退出了 app 这样当然是不允许的。


所以请在 web 页面中添加以下逻辑:



4

下载网络图片以及序列化本地


上边说了我们有这样一个需求,就是如果后台的接口返回的图片与本地序列化的图片不同,我们需要将新的图片下载到本地,然后下次进入 Splash 的时候就展示的新的图片了。


这里你需要知道知识有下边几个:


  1. java bean 序列化与反序列化的知识

  2. IntentService 服务的知识

  3. AsycTask 的使用

  4. 6.0 以上权限申请 EasyPermissions (https://github.com/googlesamples/easypermissions)的使用。

以上不熟悉的同学,看到下边的代码可能会引起适量身体不适


(1)权限管理


首先我们注意到已进入 Splash 页面我们就进行权限检查,因为我们需要下载最新的闪屏到本地,并取出序列化的对象,来展示对应的内容。


其中 checkSDCardPermission 涉及到 6.0 以上下载最新图片的逻辑,这里采用的是 官方的 EasyPermissions 来处理,关于 EasyPermissions 的使用这里就不多说了,需要了解的请移步 EasyPermissions;

https://github.com/googlesamples/easypermissions



简单来说在 EasyPermissions.hasPermissions 的回调中我们就可以正确的做我们下载图片的工作了。



(2)创建本地序列化对象 Splash Entity


Splash 内容如下:



(3)序列化反序列话的工具类 SerializableUtils


由于项目用到序列化地方还有挺多的,所以这里封装了一个序列化工具类SerializableUtils:




经过上边的努力我们已经完成了从本地反序列化内容,然后加载图片的工作了,剩下的需要做的就是下载最新图片的工作。


(4)请求接口下载最新的闪屏信息和图片


这里经过考虑,我决定采用服务去下载,因为这样可以少很多麻烦,也不影响程序的正常运行。但是绝不是你们要采用这样的方法,你们也可以单独写个工具类内部去开线程做这件事。


项目中使用开启 IntentServie 来下载图片,关于这中服务的最大的好处就是,我们不需要关注服务是否执行完任务,当他执行完 onHandleIntent 方法后他就自己挑用 stop 方法了。我们只需要关注下载逻辑和序列化逻辑就好。


checkSDCardPermission 中调用的 startImageDownLoad() 方法:


 private void startImageDownLoad() {
    SplashDownLoadService.startDownLoadSplashImage(this,
         Constants.DOWNLOAD_SPLASH);
 }


SplashDownLoadService 内容,IntentService 在调用了 startService 后会执行 onHandleIntent 方法,在这方法中我们去请求服务器最新的数据即 loadSplashNetDate:



由于是公司项目,请求方法就不给出了,但是需要讲下请求数据后如何判断是否需要执行下载任务:



getSplashLocal 方法即反序列话本地存储的 Splash Entity 的过程,上边已经给出这里就不细说,主要讲一下判断逻辑 isNeedDownLoad:



分隔 uri 取图片名称的方法:



满足下载条件后则调用 DownLoadTask 下载,



DownLoadTask:




由于下载完成后需要拿到文件存储地址这里写了一个 mDownLoadInterFace.afterDownLoad 的回调在 service 拿到回调后:



写在最后


上边 bb 这么多,我们可以看出产品一句话,我们程序员可能就需要工作一天了,所以我们需要将这个常见的功能记录下,下个公司产品再说实现一个闪屏功能,然后我们就可以说 这功能可能需要 1天时间,然后等他答应了,copy 一下,其他的时间你就可以学习下 Rxjava2 ,kotlin, js 之类的了。哈哈哈哈 我真tm机智。


如果你有想学习的文章直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递文章链接即可。


欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号: