首页 > 其他分享 >深入探讨Android启动优化策略

深入探讨Android启动优化策略

时间:2023-08-28 18:36:16浏览次数:39  
标签:初始化 启动 深入探讨 冷启动 Android 优化 加载

在当今激烈竞争的移动应用市场,应用的启动速度直接影响着用户的第一印象和满意度。作为主流的移动操作系统之一,Android的启动优化是开发者必须关注的关键领域。本文将详细介绍一些强大有效的Android启动优化策略,帮助你优化应用的启动过程,为用户创造更出色的体验。

冷启动与热启动

在着手优化之前,让我们深入了解Android应用的启动过程。Android应用的启动可分为冷启动和热启动两种情况。冷启动是指应用从完全关闭状态启动,而热启动则是从后台状态重新启动应用。尽管热启动也重要,但优化冷启动对提升用户体验影响更为显著,因为它需要加载更多资源和组件。

布局优化

应用启动时,系统需要加载布局资源并构建视图层级。因此,布局优化是提高启动速度的关键所在。

使用ConstraintLayout进行灵活布局

ConstraintLayout是一种强大且高效的布局方式,能够降低嵌套层级,从而提升布局性能。它通过定义约束关系来定位视图,减少了传统布局中频繁的测量和布局操作。

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 在此添加你的UI元素 -->

</androidx.constraintlayout.widget.ConstraintLayout>

使用ViewStub实现延迟加载

ViewStub是Android提供的一个特殊视图,充当占位符,在需要显示其内容时才会实例化和加载。在布局中使用ViewStub能够有效延迟加载视图,从而加速启动时间。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 其他UI元素 -->

    <ViewStub
        android:id="@+id/myViewStub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout="@layout/my_delayed_layout" />
</RelativeLayout>

其中@layout/my_delayed_layout是要延迟加载的布局资源的引用。

在需要显示ViewStub内容的位置,调用ViewStub.inflate()方法加载实际的布局内容:

ViewStub myViewStub = findViewById(R.id.myViewStub);
View inflatedView = myViewStub.inflate();

通常情况下,你可以根据用户交互或其他条件来触发加载。总之,与将视图设置为android:visibility="gone"相比,使用ViewStub是更好的方式实现延迟加载,特别是在启动时需要提升性能的情况下。

启动时序优化

精细控制启动时序能够显著提升启动速度,以下是一些优化策略。

呈现引人注目的闪屏界面

引入闪屏界面(Splash Screen)能够在应用加载资源的同时显示品牌标志或加载动画,缓解启动过程中的等待感。

res/values/styles.xml 中定义样式:

<style name="AppTheme.Splash" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/splash_background</item>
</style>

res/drawable 中创建 splash_background.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/splashBackgroundColor" />
    <item>
        <bitmap
            android:src="@drawable/app_logo"
            android:gravity="center" />
    </item>
</layer-list>

AndroidManifest.xml 中设置 Splash Screen 样式:

<activity
    android:name=".SplashActivity"
    android:theme="@style/AppTheme.Splash">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

降低主线程负担

主线程负责处理应用的UI操作,因此在启动过程中降低主线程工作量至关重要。

充分利用异步任务

通过将耗时任务转移到后台线程,避免了阻塞主线程。你可以使用 AsyncTaskViewModel 来管理数据和UI更新。

public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... voids) {
        // 执行耗时任务
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        // 更新UI或执行其他操作
    }
}

智能后台初始化

将启动所需的初始化工作一部分放到后台线程中处理,以更快地显示应用的核心界面。

public class StartupTask extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 在后台线程中执行初始化工作
        new Thread(() -> {
            // 执行初始化工作
        }).start();
    }
}

优化应用资源加载

在应用启动过程中,资源的加载可能是影响启动速度的一个重要因素。优化资源加载可以显著减少启动时间。

使用矢量图形资源

使用矢量图形资源(SVG、Vector Drawable)代替位图资源,可以减小APK的大小,同时适应不同屏幕密度的设备。

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_vector_image" />

压缩位图资源

使用工具如 TinyPNG 可以压缩PNG和JPEG图片,减小APK的大小。另外,确保提供各种密度的图片资源,以适应不同屏幕的设备。

使用应用冷启动优化库

Android提供了一些优秀的启动优化库,可以帮助你自动管理和减少启动时间。

使用Hilt进行依赖注入

Hilt是Android官方提供的依赖注入库。通过使用Hilt,你可以将启动时创建的依赖关系移到后台,减少主线程上的工作。

// 定义依赖关系
@Module
@InstallIn(SingletonComponent.class)
public class MyModule {
    @Provides
    public MyDependency provideMyDependency() {
        return new MyDependency();
    }
}

// 在Application中初始化Hilt
@HiltAndroidApp
public class MyApp extends Application {
}

使用Jetpack Compose重构UI

Jetpack Compose是一款现代的UI工具包,可以帮助你以声明性的方式构建界面。由于其性能优势,使用Compose可以提升应用的启动速度。

@Composable
fun MyScreen() {
    Column {
        Text(text = "Hello, Jetpack Compose!")
        Button(onClick = { /* Do something */ }) {
            Text(text = "Click me")
        }
    }
}

适当使用多进程

将某些耗时的初始化工作放在单独的进程中进行,可以减少主进程的负担,从而提升应用的启动速度。

创建后台进程

在AndroidManifest.xml中定义一个后台进程:

<application
    android:name=".MyApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:process=":background">
    <!-- ... -->
</application>

执行耗时任务

在后台进程中执行耗时任务,例如初始化某些模块或资源:

public class BackgroundProcessService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        // 在后台进程中执行耗时任务
        // ...
        stopSelf(); // 任务完成后停止服务
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

减少启动Activity的冷启动

Android的启动过程中,冷启动Activity的时间占比较大。以下是一些减少冷启动Activity时间的方法。

使用SingleTask启动模式

将冷启动Activity设置为SingleTask启动模式,可以在同一任务栈中复用已有的Activity实例,从而减少Activity的重复创建。

<activity
    android:name=".MainActivity"
    android:launchMode="singleTask">
</activity>

使用Splash Screen优化冷启动体验

在Splash Screen中执行一些初始化操作,如预加载数据,从而将部分冷启动时间移至Splash Screen阶段。

public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 执行初始化操作,如预加载数据
        // ...
        startActivity(new Intent(this, MainActivity.class));
        finish();
    }
}

借助第三方开源库

android-startup提供一种在应用启动时能够更加简单、高效的方式来初始化组件。开发人员可以使用android-startup来简化启动序列,并显式地设置初始化顺序与组件之间的依赖关系。 与此同时android-startup支持同步与异步等待,并通过有向无环图拓扑排序的方式来保证内部依赖组件的初始化顺序。

添加依赖

repositories {
    mavenCentral()
}
dependencies {
    implementation 'io.github.idisfkj:android-startup:1.1.0'
}

定义初始化的组件

每一个初始化的组件都需要实现AndroidStartup抽象类,它实现了Startup接口。 例如,下面定义一个SampleSecondStartup类来实现AndroidStartup抽象类:

class SampleSecondStartup : AndroidStartup<Boolean>() {

    override fun callCreateOnMainThread(): Boolean = false

    override fun waitOnMainThread(): Boolean = true

    override fun create(context: Context): Boolean {
        // 模仿执行耗时
        Thread.sleep(5000)
        return true
    }

    override fun dependenciesByName(): List<String> {
        return listOf("com.rousetime.sample.startup.SampleFirstStartup")
    }

}

在dependenciesByName()方法中返回了com.rousetime.sample.startup.SampleFirstStartup,所以它能保证SampleFirstStartup优先执行完毕。

启动配置

提供两种配置,Manifiest中自动配置与Application中手动配置 下面给出自动配置示例:

<provider
    android:name="com.rousetime.android_startup.provider.StartupProvider"
    android:authorities="${applicationId}.android_startup"
    android:exported="false">

    <meta-data
        android:name="com.rousetime.sample.startup.SampleFourthStartup"
        android:value="android.startup" />

</provider>

在Android Startup中提供了StartupProvider类,它是一个特殊的content provider,提供自动识别在manifest中配置的初始化组件。 为了让其能够自动识别,需要在StartupProvider中定义标签。其中的name为定义的组件类,value的值对应为android.startup。

合理的管理启动任务,将会极大的提高应用的启动时间,获得更佳的启动体验。

结论

通过优化应用资源加载、使用优秀的启动优化库、适当使用多进程以及减少冷启动Activity的时间,你可以进一步提升Android应用的启动速度,为用户创造更佳的启动体验。不同的优化策略可以相互协作,以达到更好的效果。

标签:初始化,启动,深入探讨,冷启动,Android,优化,加载
From: https://blog.51cto.com/u_16175630/7265849

相关文章

  • Android Audio
    1.最常接触到的audioserviceframeworks\base\services\core\java\com\android\server\audio\AudioService.java初始化音量的代码//Initializevolume//Priority1-AndroidProperty//Priority2-AudioPolicyService//Priority3-Defau......
  • cocos2dx 如何编译android 打包
    先要配置NDK,然后启动CMD命令进入到自己的游戏根目录,我的是starGame,所以如上所示:......
  • 迅为RK3588开发板Android12 设置系统默认不锁屏
    修改frameworks/base/packages/SettingsProvider/res/values/defaults.xml文件,修改为如下所示:-<boolname="def_lockscreen_disabled">false</bool>+<boolname="def_lockscreen_disabled">true</bool>修改完,保存修改,重新编译android源码。......
  • 从原理聊 JVM(五):JVM 的编译过程和优化手段
    一、前端编译前端编译就是将Java源码文件编译成Class文件的过程,编译过程分为4步:1准备初始化插入式注解处理器(AnnotationProcessingTool)。2解析与填充符号表将源代码的字符流转变为标记(Token)集合,构造出抽象语法树(AST)。抽象语法树每个节点都代表着程序代码中的一个语法结......
  • android多模块 安卓模块是什么意思
    模块化在进入组件化之前,我们先说一下模块化。一个功能分为一个模块,例如登录模块,支付模块,广告模块。传统的开发模式中一个模块就是一个Module(也有不同模块放在不同包里面的情况)。模块在功能上对代码进行了划分,但是在开发上任然存在问题。例如 当需要debug某一个模块的时候此......
  • 批量python爬虫采集性能优化之减少网络延迟的方法
    今天,我们将一起探讨批量爬虫采集的性能优化,特别关注减少网络延迟的方法。网络延迟是爬虫程序中一个常见的性能瓶颈,通过优化网络延迟,我们可以提高爬虫程序的采集速度和效率。让我们一起来看看如何实现这一目标。1.使用异步请求传统的同步请求方式会导致爬虫程序在等待服务器响应时浪......
  • 直播商城源码,android xml中设置水平虚线及竖直虚线
    直播商城源码,androidxml中设置水平虚线及竖直虚线水平虚线:line_stroke <?xmlversion="1.0"encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"  android:shape="line">  <stroke    and......
  • 成品直播源码推荐,android自定义显示图片+文字
    成品直播源码推荐,android自定义显示图片+文字 /** *@authorMartin-harry *@date2021/8/10 *@address *@Desc自定义toast */publicclassToastUtil{  /**   *显示文本+图片   *@paramcontext   *@parammessage   */  publicsta......
  • 介绍一下Oracle的操作符优化
    IN:IN写出来的SQL比较容易写及清晰易懂但是性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:ORACLE试图将IN转换成多个表的连接,如果转换不成功会先执行IN里面的子查询,再查询外层的表记录,如果转换成功,则直接采用多个表的连接方式查询。所以用IN的SQL至......
  • 10条SQL优化技巧
    一、一些常见的SQL实践(1)负向条件查询不能使用索引select*fromorderwherestatus!=0andstauts!=1notin/notexists都不是好习惯可以优化为in查询:select*fromorderwherestatusin(2,3)(2)前导模糊查询不能使用索引select*fromorderwheredesclike‘%XX’而非前导模糊......