Android 加载时显示启动画面

Android display Splash-Screen while loading

我有一个 Android 应用程序,它显示 "Splash Screen" 3 秒。之后,加载 MainActivity。

不幸的是,MainActivity 需要大约 4 秒的时间来加载。在第一次启动时甚至更长。但是当应用程序加载时,一切运行顺利。

现在我该如何实现,在启动画面显示期间加载 MainActivity?它应该只显示一个图像,直到整个东西完全加载。 我已经阅读了有关 Async-Task 的信息,但我不确定将它放在哪里以及如何正确使用它。有人可以帮我吗?

SplashScreen.java

public class SplashScreen extends Activity {
    private static int SPLASH_TIME_OUT = 3000;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_startup);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent i = new Intent(SplashScreen.this, MainActivity.class);
                startActivity(i);
                finish();
            }
        }, SPLASH_TIME_OUT);
    }
}

MainActivity.java

public class MainActivity extends Activity implements OnClickListener, MediaController.MediaPlayerControl {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Some heavy processing
        //starting services
        //starting Google Text to Speech
        //and so on...

    }

}

您的初始屏幕代码工作正常,但是当您调用 next activity 然后在 onCreate() 中使用 Asynctask 来完成繁重的任务...

如果对启动画面的显示时间没有具体限制,您可以按以下方式使用AsyncTask

public class SplashScreen extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_startup);
        startHeavyProcessing();

    }

    private void startHeavyProcessing(){
       new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            //some heavy processing resulting in a Data String
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "whatever result you have";
        }

        @Override
        protected void onPostExecute(String result) {
            Intent i = new Intent(SplashScreen.this, MainActivity.class);
            i.putExtra("data", result);
            startActivity(i);
            finish();
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}

如果结果数据的性质不同于字符串,您可以将 Parcelable 对象作为 activity 的额外内容。在 onCreate 中,您可以通过以下方式检索数据:

getIntent().getExtras.getString('data');

如何,为了简单起见,将启动画面 activity 与主要 activity 结合起来怎么样?这样您就可以两全其美,即在您的数据第一次准备时显示启动画面,并在之前准备好数据时快速启动。让用户什么都不等待不是很好的形式...

类似于:

public class MainActivity extends Activity implements OnClickListener, MediaController.MediaPlayerControl {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initially shows splash screen, the main UI is not visible
        setContentView(R.layout.activity_main);  

        // Start an async task to prepare the data. When it finishes, in
        // onPostExecute() get it to call back dataReady()
        new PrepareDataAsyncTask(this).execute();

    }

    public void dataReady() {
        // Hide splash screen
        // Show real UI
    }

}

您不应在启动时创建新线程,而应创建不必等待资源加载的视图,如本文所述:Splash Screens the Right Way.

如文章所述,您应该创建一个 layer-list 可绘制对象而不是 layout XML 文件:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Fill the background with a solid color -->
    <item android:drawable="@color/gray"/>

    <!-- Place your bitmap in the center -->
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

然后使用可绘制文件作为背景创建主题。我使用 background 属性而不是文章中建议的 windowBackground 属性,因为 background 考虑了状态和导航栏,更好地使可绘制对象居中。我还将 windowAnimationStyle 设置为 null,这样启动画面就不会动画过渡到 MainActivity:

<resources>

    <!-- Base application theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

    <!-- Splash Screen theme -->
    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:background">@drawable/background_splash</item>
        <item name="android:windowAnimationStyle">@null</item>
    </style>

</resources>

然后在清单中为您的 SplashActivity:

声明您的主题
<activity android:name=".SplashActivity"
    android:theme="@style/SplashTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

最后,您在 SplashActivity 中所要做的就是启动您的 MainActivity,启动画面只会在您的应用配置时显示:

public class SplashActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

我遇到过类似的问题。有一个空白的加载屏幕(甚至没有工具栏)。 Mu 罪魁祸首在 MainActivity 的清单中:

 android:launchMode="singleInstance"

就像this article中的那样:

1 - 为初始屏幕创建这样的 XML 布局。我称它为“background_splash.xml”

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@color/cardview_light_background"/>

    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/kiss_com_sub_logo"/>
    </item>

</layer-list>

2 - 然后,转到 styles.xml 并编写如下样式:

<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/background_splash</item>
</style>

3 - 给您的启动栏写一个 activity。我叫它 SplashActivity.kt

class SplashActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val intent = Intent(this, MainActivity::class.java)
        startActivity(intent)
        finish()
    }
}

4 - 最后,去找你 AndroidManifest.xml 并添加你的 activity 启动画面:(注意:不要删除 AndroidManifest 中的任何内容,只需在 Main activity 之前添加它).

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

大功告成。您无需担心您的应用程序需要多少时间才能启动,启动画面会在那里停留足够长的时间。当您的 MainActivity 准备就绪时,它将显示出来。