当前位置:网站首页>App 启动速度优化系列:如何用一个placeholderUI来做初始化工作
App 启动速度优化系列:如何用一个placeholderUI来做初始化工作
2022-08-10 22:54:00 【Android技术栈】
1,代码分析
因为App集成了Bugly, Push, Feedback等服务, 所以Application的onCreate有很多第三方平台的初始化工作
public class GithubApplication extends MultiDexApplication {
@Override
public void onCreate() {
super.onCreate();
// init logger.
AppLog.init();
// init crash helper
CrashHelper.init(this);
// init Push
PushPlatform.init(this);
// init Feedback
FeedbackPlatform.init(this);
// init Share
SharePlatform.init(this);
// init Drawer image loader
DrawerImageLoader.init(new AbstractDrawerImageLoader() {
@Override
public void set(ImageView imageView, Uri uri, Drawable placeholder) {
ImageLoader.loadWithCircle(GithubApplication.this, uri, imageView);
}
});
}
}
2,调整Application onCreate再试
知道了哪些地方耗时长, 我们不妨调整下Application的onCreate实现, 一般来说我们可以将这些初始化放在一个单独的线程中处理, 为了方便今后管理, 这里我用了一个InitializeService的IntentService来做初始化工作
明确一点, IntentService不同于Service, 它是工作在后台线程的
InitializeService.java代码如下:
package com.anly.githubapp.compz.service;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.widget.ImageView;
import com.anly.githubapp.common.wrapper.AppLog;
import com.anly.githubapp.common.wrapper.CrashHelper;
import com.anly.githubapp.common.wrapper.FeedbackPlatform;
import com.anly.githubapp.common.wrapper.ImageLoader;
import com.anly.githubapp.common.wrapper.PushPlatform;
import com.anly.githubapp.common.wrapper.SharePlatform;
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader;
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
/** * Created by mingjun on 16/8/25. */
public class InitializeService extends IntentService {
private static final String ACTION_INIT_WHEN_APP_CREATE = "com.anly.githubapp.service.action.INIT";
public InitializeService() {
super("InitializeService");
}
public static void start(Context context) {
Intent intent = new Intent(context, InitializeService.class);
intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
performInit();
}
}
}
private void performInit() {
AppLog.d("performInit begin:" + System.currentTimeMillis());
// init Drawer image loader
DrawerImageLoader.init(new AbstractDrawerImageLoader() {
@Override
public void set(ImageView imageView, Uri uri, Drawable placeholder) {
ImageLoader.loadWithCircle(getApplicationContext(), uri, imageView);
}
});
// init crash helper
CrashHelper.init(this.getApplicationContext());
// init Push
PushPlatform.init(this.getApplicationContext());
// init Feedback
FeedbackPlatform.init(this.getApplication());
// init Share
SharePlatform.init(this.getApplicationContext());
AppLog.d("performInit end:" + System.currentTimeMillis());
}
}
GithubApplication的onCreate改成:
public class GithubApplication extends MultiDexApplication {
@Override
public void onCreate() {
super.onCreate();
// init logger.
AppLog.init();
InitializeService.start(this);
}
}
3,给我们的应用窗口弄一个PlaceHolder
Android最新的Material Design 建议我们使用一个placeholder UI来展示给用户直至App加载完毕
怎么做呢?
1>:给Window加上背景
当App没有完全起来时, 屏幕会一直显示一块空白的窗口(一般来说是黑屏或者白屏, 根据App主题)
这个空白的窗口展示跟主题相关, 那么我们是不是可以从首屏的主题入手呢? 恰好有一个windowBackground的主题属性, 我们来给Splash界面加上一个主题, 带上我们想要展示的背景。
做一个logo_splash的背景:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 底层白色 -->
<item android:drawable="@color/white" />
<!-- 顶层Logo居中 -->
<item>
<bitmap
android:gravity="center"
android:src="@drawable/ic_github" />
</item>
</layer-list>
做一个主题:
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowBackground">@drawable/logo_splash</item>
</style>
2>:将一个什么也不渲染布局的Activity作为启动屏
写一个什么都不做的LogoSplashActivity
public class LogoSplashActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 注意, 这里并没有setContentView, 单纯只是用来跳转到相应的Activity.
// 目的是减少首屏渲染
if (AppPref.isFirstRunning(this)) {
IntroduceActivity.launch(this);
}
else {
MainActivity.launch(this);
}
finish();
}
}
在AndroidManifest.xml中设置其为启动屏, 并加上主题:
<activity
android:name=".ui.module.main.LogoSplashActivity"
android:screenOrientation="portrait"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
这种优化,对于有些Application内的初始化工作不能移到子线程做的情况, 是非常友好的;可以避免我们的App长时间的呈现给用户一个空白的窗口
有需要文中完整代码的同学可以在评论区下方留言 “底层源码” 或者可以直接私信我即可 免费获取
最后我想说:
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们
技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面
Android 架构师之路还很漫长,与君共勉
边栏推荐
- 计算需要的MIPI lane数目
- 常用代码扩展点设计方式
- 消息队列总结
- Introduction to the use of counter instructions in Rockwell AB PLC RSLogix5000
- How to bounce the shell
- Fatal error: cstring: No such file or directory
- 【秋招】【更新中ing】手撕代码系列
- Detailed installation steps and environment configuration of geemap
- Three major logs in mysql
- PyQt5 窗口自适应大小
猜你喜欢
随机推荐
JS学习 2022080
Distribution Network Expansion Planning: Consider Decisions Using Probabilistic Energy Production and Consumption Profiles (Matlab Code Implementation)
高精度减法
Pytorch面试题面经
【640. Solving Equations】
Btree索引和Hash索引
服务器上行带宽和下行带宽指的是什么
OneNote 教程,如何在 OneNote 中整理笔记本?
小程序平台工具如何选择和使用?
Three major logs in mysql
PlaidCTF 2022 Amongst Ourselves: Shipmate writeup
房间虚拟样板间vr制作及价格
从零开始配置 vim(7)——自动命令
Ndk 和Cmake报错解决
IFIT的架构与功能
LabVIEW分配多少线程?
确诊了!是Druid1.1.20的锅,查询无法映射LocalDateTime类型(带源码解析及解决方案)
MySQL之JDBC编程增删改查
MySQL: MySQL Cluster - Principle and Configuration of Master-Slave Replication
XSLeaks 侧信道攻击 (unfinished)









