Android display Splash-Screen while loading
You should not be creating a new thread on startup, instead you should create a view that does not have to wait for your resources to load, as detailed in this article: Splash Screens the Right Way.
As stated in the article, you should create a layer-list
drawable instead of a layout
XML file:
<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>
Then create a theme using the drawable file as a background. I use the background
attribute instead of the windowBackground
attribute as suggested in the article, because background
takes the status and navigation bars into account, centering the drawable better. I also set windowAnimationStyle
to null
so that the splash screen does not animate the transition to the 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>
Then declare your theme in the manifest for your 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>
And finally all you have to do in your SplashActivity
is start your MainActivity
, and the splash screen will only show for as long as it takes for your app to configure:
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
If there are no specific constraints about the time the splash screen should be shown, you could use the AsyncTask
in the following way:
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) {}
}
}
If the resulting data if of another nature than a String you could put a Parcelable
Object as an extra to your activity. In onCreate
you can retrieve the data with:
getIntent().getExtras.getString('data');
How about, in the interest of simplicity, you combine your splash activity with your main activity? That way you get the best of both worlds, namely a splash screen while your data is preparing the first time, and a quick startup when it's been prepared previously. Making the user wait for nothing is not really good form...
Something like:
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
}
}