本篇文章已授权微信公众号AndroidChinaNet(Android开发中文站)独家发布

在做食生活的项目时,曾遇到也启动页加载很慢,白屏。不知道是什么原因,后来换了一种思想,这个思想也用在了我的另一个项目里,感觉还挺实用的,现在将其总结余一下分享给大家(图片中有一个优化方法哦!)。

(1)Instant Run造成的白屏或者黑屏现象

Instant Run是用来做什么的?就是你点击是用来提升开发效率的,在Android Studio 2.0及以上有了很大改善,使用instant run,在第一次运行之后,就可以快速的在真机中看见修改后的结果,不仅仅是UI可以直接显示,还包括代码逻辑。不用再苦苦等build了!也就是说,只有在开发阶段才会有Instant Run这个东西,在正式的产品中是完全不存在Instant Run的!

所以如果你是直接点击按钮啊或者是debug版本的时候出现白屏或者黑屏,最好生成一个release版的程序就不会出现这种现象了。

(2)App的启动过程

如果想要优化我们的app,那么我们就要深入他,理解他。下面,简单解释一下Activity的启动过程:

  • 1.Application 构造方法

  • 2.attachBaseContext()

  • 3.onCreate()

  • 4.入口Activity的对象构造

  • 5.setTheme() 设置主题等信息

  • 6.入口Activity的onCreate()

  • 7.入口Activity的onStart()

  • 8.入口Activity的onResume()

  • 9.入口Activity的onAttachToWindow()

  • 10.入口Activity的onWindowFocusChanged()

根据上面的信息,我们就能得到一些额如何减少应用启动时的耗时的信息了,是不是很一目了然?

针可上面的过程我们来思考,采取以下策略:

1、在Application的构造器方法、attachBaseContext()、onCreate()方法中不要进行耗时操作的初始化,一些数据预取放在异步线程中,可以采取回调的方法来去实现。

2、对于sp的初始化,因为sp的特性在初始化时候会对数据全部读出来存在内存中,所以这个初始化放在主线程中不合适,反而会延迟应用的启动速度,对于这个还是需要放在异步线程中处理。

3、对于MainActivity,由于在获取到第一帧前,需要对contentView进行测量布局绘制操作,尽量减少布局的层次,考虑StubView的延迟加载策略,当然在onCreate、onStart、onResume方法中避免做耗时操作。

优化应用启动时的体验

对于应用的启动时间,只能是尽量的避免一些耗时的、非必要的操作在主线程中,这样相对可以缩减一部分启动的耗时。

另外一方面在等待第显示的时间里,如加入Activity的background,这个背景会在显示第一帧前提前显示在界面上,可以通过视觉的欺骗,以让人看着启动时间变快了。

方案:通过设置Style

(1)设置背景图Theme

设置一张背景图。 当程序启动时,首先显示这张背景图,背景图的选择最好和主页面色调相近,避免出现黑屏或者白屏。

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"><item name="android:screenOrientation">portrait</item><item name="android:windowBackground">>@mipmap/splash</item><item name="android:windowIsTranslucent">true</item><item name="android:windowNoTitle">true</item></style>

(2)设置透明Theme

通过把样式设置为透明,程序启动后不会黑屏而是整个透明了,等到界面初始化完才一次性显示出来

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"><item name="android:windowNoTitle">true</item><item name="android:windowBackground">@android:color/transparent</item><item name="android:windowIsTranslucent">true</item><item name="android:screenOrientation">portrait</item></style>

这样是不是感觉稍微快了一点啊?

(3)App的启动页的优化过程

1)、 ViewFlipper的巧妙利用。

ViewFlipper是继承至FrameLayout的,所以它是一个Layout里面可以放置多个View(FrameLayout和糖炒栗子一样,是个好东西啊)。

ViewFlipper一般用来实现滑动翻页,经常和Viewpager一起做比较。因为项目中要用到轮播,所以仔细的看了看他们的源码,后来发现切换操作是通过ViewAnimator提供的方法setDisplayedChild(…)实现的。

FrameLayout的布局上下重叠,setDisplayedChild(…)来实现显示某个View或ViewGroup,而其他的都会设置为Gone,进源码看一下:

 public void setDisplayedChild(int whichChild) {mWhichChild = whichChild;if (whichChild >= getChildCount()) {mWhichChild = 0;//从0开始,1,2....} else if (whichChild < 0) {mWhichChild = getChildCount() - 1;}boolean hasFocus = getFocusedChild() != null;// This will clear old focus if we had itshowOnly(mWhichChild);if (hasFocus) {// Try to retake focus if we had itrequestFocus(FOCUS_FORWARD);}}void showOnly(int childIndex) {final boolean animate = (!mFirstTime || mAnimateFirstTime);showOnly(childIndex, animate);} void showOnly(int childIndex, boolean animate) {final int count = getChildCount();for (int i = 0; i < count; i++) {final View child = getChildAt(i);if (i == childIndex) {if (animate && mInAnimation != null) {child.startAnimation(mInAnimation);}child.setVisibility(View.VISIBLE);mFirstTime = false;} else {if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {child.startAnimation(mOutAnimation);} else if (child.getAnimation() == mInAnimation)child.clearAnimation();child.setVisibility(View.GONE);//从这里看出来}}}

晒出我的布局,和逻辑处理(很简单,但是很实用)

布局可以使用ViewStub的形式进行懒加载,我这里没有用到。

代码内处理:

2)、 巧用Fragment,Fragment大法就是好

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:

帅气的Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个Fragment(解决问题的思路)

优化方向:

把SplashActivity改成SplashFragment,应用程序的入口仍然是MainActivity,在MainActivity中先展示SplashFragment

当SplashFragment显示完毕后再将它remove,同时在SplashFragment的2S的友好时间内进行网络数据缓存,在窗口加载完毕后,我们加载activity_main的布局,考虑到这个布局有可能比较复杂,耽误View的解析时间,采用ViewStub的形式进行懒加载。

ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。

代码:
AnotherActivity.java

AnotherActivity布局:

SplashFragment.java

SplashFragment布局:

mainlayout.xml布局:

优化思路及办法

  • 1、避免启动页UI的过度绘制,减少UI重复绘制时间,打开设置中的GPU过度绘制开关,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一;

  • 2、主线程中的所有SharedPreference能否在非UI线程中进行,SharedPreferences的apply函数需要注意,因为Commit函数会阻塞IO,这个函数虽然执行很快,但是系统会有另外一个线程来负责写操作,当apply频率高的时候,该线程就会比较占用CPU资源。类似的还有统计埋点等,在主线程埋点但异步线程提交,频率高的情况也会出现这样的问题。

  • 3、 对于首次启动的黑屏问题,对于“黑屏”是否可以设计一个.9图片替换掉,间接减少用户等待时间。

+ 4、对于网络错误界面,友好提示界面,使用ViewStub的方式,减少UI一次性绘制的压力。

本文源码gthub地址

Android app 启动优化相关推荐

  1. Android App启动优化

    一:启动优化 1. 启动状态 应用有三种启动状态,冷启动.温启动与热启动:每种启动状态都会影响该应用向用户显示所需的时间. 在冷启动中,应用从头开始启动. 在另外两种状态中,系统需要将后台运行的应用带 ...

  2. Android 系统性能优化(72)-----App启动优化

    App启动优化的一篇深度好文 原文地址: http://www.jianshu.com/p/c056e63dc7a2 正文 对于Android平台上的线程优先级设置来说可以处理很多并发线程的阻塞问题, ...

  3. Android性能优化(一):APP启动优化

    Android性能优化(一):APP启动优化 性能优化系列文章: Android性能优化(一):APP启动优化 Android性能优化(二):UI布局优化 Android性能优化(三):响应优化 An ...

  4. android启动分析,Android APP启动方式、启动流程及启动优化分析

    本文章向大家介绍Android app应用启动的一些相关知识,包括app启动方式.app启动流程和app启动优化等知识! app应用启动方式 1.冷启动 当启动应用时,后台没有该应用的进程,这时系统会 ...

  5. 【转】Android APP 启动黑屏优化补丁 (2016-01-18 10:35:23)

    [转]Android APP 启动黑屏优化补丁 (2016-01-18 10:35:23) 转载▼ 这个必须转,这才是高手,解决官方都解决不好的问题! 原文地址,以下为转贴内容: 使用说明 ***** ...

  6. Android APP性能优化

    转载自:https://www.cnblogs.com/qwangxiao/p/8727229.html Android APP性能优化(最新总结) 导语 安卓大军浩浩荡荡,发展已近十个年头,技术优化 ...

  7. Android 系统(102)---Android APP耗电优化

    Android APP耗电优化 可能造成耗电的一些原因 网络请求耗电,而且手机数据网络进行http请求比无线网进行http请求更加耗电,因为数据网络调用到一些底层的硬件模块,就如GPS一样,当手机打开 ...

  8. Android APP性能优化(一)

    Android APP性能优化(最新总结) 安卓大军浩浩荡荡,发展已近十个年头,技术优化日异月新,如今Android 8.0 Oreo 都发布了,Android系统性能已经非常流畅了.但是,到了各大厂 ...

  9. App启动优化-一顿操作猛如虎

    前言 ++一个应用App的启动速度能够影响用户的首次体验,用户希望应用能够及时响应并快速加载.启动时间过长的应用不能满足这个期望,并且可能会令用户失望.这种糟糕的体验可能会导致用户在应用商店针对您的应 ...

  10. Android App性能优化之内存优化

    为什么要进行内存优化? 1.App运行内存限制,OOM导致App崩溃 2.App性能:流畅性.响应速度和用户体验 Android的内存管理方式 Android系统内存分配与回收方式 ●   一个App ...

最新文章

  1. 8.6 GOF设计模式四: 策略模式… Strategy Pattern
  2. Talk O/RM (DAL) too ...
  3. 【软件期刊01】2017-02-22
  4. Get busy living or get busy dying
  5. Clinicast让癌症治疗不那么昂贵
  6. linux单次任务调度,go任务调度2(linux的cron调用)
  7. c语言设计阶段作业答案,C语言程序设计阶段考试练习题(答案)
  8. matlab 简单低通滤波器,简单低通滤波器设计及matlab仿真.doc
  9. txt数据文件的读写操作
  10. 网页设计中有效的配色
  11. Android SDK ADB命令行总结
  12. iOS中3DTouch的使用
  13. 程序员笔试题收集汇总(三)
  14. Finger.02 - 搭建MQTT服务器
  15. MCE公司:M525-针对混合谱系白血病(MLL)的新型抑制剂
  16. rss阅读器保存html文件,4款在线RSS阅读器使用体验
  17. scrapy 两类item_手把手教你进行Scrapy中item类的实例化操作
  18. 计算机中乘法是什么函数,excl中的乘法函数符号是什么
  19. 解决win10搜索框无法搜索本地应用或无任何反应
  20. python 3.10上安装pyqt5

热门文章

  1. 自动驾驶 Automotive SPICE(ISO/IEC 15504) 和CMMI有什么不同?
  2. 近来比较有意思的新形式网络广告
  3. CRM项目半途而废 “烂摊子”该如何收拾?
  4. matlab 连续下标表示,matlab 下标问题
  5. redis中字符串(String)类型常见命令操作 (附有示例)
  6. 软件系统部署手册模版
  7. php设置个性域名,利用nginx泛域名解析配置二级域名和多域名,实现二级域名子站,用户个性独立子域名。...
  8. 摄像头M-JPEG 格式分析
  9. 任意进制转换(2进制、8进制、16进制等)
  10. C++类内初始值的初始化形式