Android - Mencegah layar putih saat startup


110

Seperti yang kita semua ketahui, banyak aplikasi Android menampilkan layar putih dengan sangat singkat sebelum aplikasi pertama Activitydifokuskan. Masalah ini diamati dalam kasus berikut:

  • Aplikasi Android yang memperluas Applicationkelas global dan melakukan inisialisasi utama di dalamnya. The Application objek selalu dibuat sebelum pertama Activity(sebuah fakta yang dapat diamati di debugger), jadi ini masuk akal. Inilah penyebab keterlambatan dalam kasus saya.

  • Aplikasi Android yang menampilkan jendela pratinjau default sebelum splash screen.

Pengaturan android:windowDisablePreview = "true"jelas tidak berfungsi di sini. Saya juga tidak dapat menyetel tema induk layar splash Theme.Holo.NoActionBarseperti yang dijelaskan di sini , karena [sayangnya] layar splash saya menggunakan file ActionBar.

Sementara itu, aplikasi yang tidak memperluas Applicationkelas tidak menampilkan layar putih saat pengaktifan.

Masalahnya, idealnya inisialisasi yang dilakukan di Applicationobjek perlu terjadi sebelum yang pertama Activityditampilkan. Jadi pertanyaan saya adalah, bagaimana saya bisa melakukan inisialisasi ini pada startup aplikasi tanpa menggunakan Applicationobjek? Mungkin menggunakan Threadatau Service, saya kira?

Ini adalah masalah yang menarik untuk dipikirkan. Saya tidak dapat mem-bypassnya dengan cara biasa (dengan mengatur NoActionBartema), karena tragisnya layar Splash saya sebenarnya memiliki ActionBarbeberapa alasan yang tidak terkait.

catatan:

Saya telah merujuk pada pertanyaan-pertanyaan berikut:

Referensi:


1
Anda menemukan masalahnya sendiri, Anda melakukan ke banyak init dalam konteks aplikasi, memblokir pemuatan aktivitas, mencoba untuk menyinkronkan ini, membiarkan aktivitas pemuatan muncul hingga beberapa utas berakhir.
AxelH

Ini mungkin membantu
Max

1
Idealnya, aplikasi akan membongkar pemrosesan dan tidak menggunakan utas utama untuk operasi yang lama. Ini adalah praktik yang diterima dengan baik. Jika operasi perlu terjadi sebelum aplikasi dimuat, setidaknya aplikasi tersebut tidak boleh berbagi thread dengan UI.
Beshoy Hanna

1
Anda mungkin menemukan bahwa ini masih menjadi masalah setelah Anda memindahkan semua kode inisialisasi keluar dari Applicationkelas. Hal ini disebabkan oleh cara Android yang lebih baru untuk "memulai secara dingin" aplikasi. Google sebenarnya membahas waktu peluncuran di Google I / O tahun ini dan itu akan diperbaiki di N dari yang saya ingat. Sementara itu, Anda harus melihat apa yang disebut Google sebagai "layar peluncuran bermerek". Berikut adalah contoh cara membuatnya: antonioleiva.com/branded-launch-screen - tidak ada lagi layar putih di awal ;-) Dan tolong jangan gunakan splashscreens - itu mengganggu pengguna.
Darwind

1
Wrt theme, triknya bukanlah menyetel tema NoActionBar, ini untuk menyesuaikan tema aktivitas awal sehingga layar bertema kosong terlihat seperti yang diinisialisasi sepenuhnya.
zapl

Jawaban:


86

Masalah dengan latar belakang putih disebabkan karena android mulai dingin saat aplikasi dimuat ke memori, dan ini dapat dihindari dengan ini:

public class OnboardingWithCenterAnimationActivity extends AppCompatActivity {
public static final int STARTUP_DELAY = 300;
public static final int ANIM_ITEM_DURATION = 1000;
public static final int ITEM_DELAY = 300;

private boolean animationStarted = false;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    setTheme(R.style.AppTheme);
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_onboarding_center);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {

    if (!hasFocus || animationStarted) {
        return;
    }

    animate();

    super.onWindowFocusChanged(hasFocus);
}

private void animate() {
    ImageView logoImageView = (ImageView) findViewById(R.id.img_logo);
    ViewGroup container = (ViewGroup) findViewById(R.id.container);

    ViewCompat.animate(logoImageView)
        .translationY(-250)
        .setStartDelay(STARTUP_DELAY)
        .setDuration(ANIM_ITEM_DURATION).setInterpolator(
            new DecelerateInterpolator(1.2f)).start();

    for (int i = 0; i < container.getChildCount(); i++) {
        View v = container.getChildAt(i);
        ViewPropertyAnimatorCompat viewAnimator;

        if (!(v instanceof Button)) {
            viewAnimator = ViewCompat.animate(v)
                    .translationY(50).alpha(1)
                    .setStartDelay((ITEM_DELAY * i) + 500)
                    .setDuration(1000);
        } else {
            viewAnimator = ViewCompat.animate(v)
                    .scaleY(1).scaleX(1)
                    .setStartDelay((ITEM_DELAY * i) + 500)
                    .setDuration(500);
        }

        viewAnimator.setInterpolator(new DecelerateInterpolator()).start();
    }
}
}

tata letak

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?colorPrimary"
android:orientation="vertical"
>

<LinearLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center"
    android:orientation="vertical"
    android:paddingTop="144dp"
    tools:ignore="HardcodedText"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        android:alpha="0"
        android:text="Hello world"         android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
        android:textColor="@android:color/white"
        android:textSize="22sp"
        tools:alpha="1"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="8dp"
        android:alpha="0"
        android:gravity="center"
        android:text="This a nice text"
      android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse"
        android:textSize="20sp"
        tools:alpha="1"
        />

    <Button
        android:id="@+id/btn_choice1"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:scaleX="0"
        android:scaleY="0"
        android:text="A nice choice"
        android:theme="@style/Button"
        />

    <Button
        android:id="@+id/btn_choice2"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:scaleX="0"
        android:scaleY="0"
        android:text="Far better!"
        android:theme="@style/Button"
        />

</LinearLayout>

<ImageView
    android:id="@+id/img_logo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/img_face"
    tools:visibility="gone"
    />
</FrameLayout>

img wajah

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

<item android:drawable="?colorPrimary"/>
<item>
    <bitmap
        android:gravity="center"
        android:src="@drawable/img_face"/>
</item>

Tambahkan tema ini ke layar splash Anda di manifes

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowBackground">@null</item>
</style>

<style name="AppTheme.CenterAnimation">
    <item name="android:windowBackground">@drawable/ll_face_logo</item>
</style>

yang akan menghasilkan efek seperti ini

kucing yang sibuk

untuk lebih jelasnya dan lebih banyak solusi anda bisa cek BlogPost ini


3
itu tidak membantu layar putih dan animasi pada akhirnya
Mehvish Ali

Ini adalah implementasi langsung. Mungkin ada beberapa bagian lain dari kode Anda yang menyebabkan masalah. Silakan buka pertanyaan lain dan saya akan ada untuk membantu Anda :)
Ivan Milisavljevic

1
Saya memecahkan masalah ini dengan menganimasikan antara tema dan mengubah tema tanpa drawable tetapi hanya warna belakang yang sama dan kemudian onWindowFocusChanged () membuat konten terlihat dan animasinya, selain itu, di antara transisi juga. animasi tema banyak membantu
Mehvish Ali

93

tolong tambahkan baris ini ke dalam tema aplikasi Anda

<item name="android:windowDisablePreview">true</item>

untuk informasi lebih lanjut: https://developer.android.com/topic/performance/vitals/launch-time#themed


25
Itu menggantung aplikasi selama 2 detik dan kemudian meluncurkan aplikasi, tidak berguna bagi saya!
Faakhir

4
parut sekarang tidak menunjukkan warna #ffffff tetapi sekarang menunjukkan # 000000
Midhilaj

@Faakhir Jadi, apakah Anda menemukan solusi? Saya masih mencari solusi, yaitu menghapus layar putih ini dan juga tidak ada penundaan pada waktu peluncuran.
Rupam Das

33

Silakan salin dan tempel dua baris ini di tema aplikasi manifes Anda, yaitu res / styles / AppTheme. maka itu akan bekerja seperti pesona ..

<item name="android:windowDisablePreview">true</item>
<item name="android:windowIsTranslucent">true</item>


20

Cara yang disarankan untuk memecahkan masalah ini tidak ada di jawaban. Jadi saya menambahkan jawaban saya di sini. Masalah layar putih saat memulai terjadi karena layar kosong awal yang dibuat oleh proses sistem saat meluncurkan aplikasi. Cara umum untuk mengatasinya adalah dengan mematikan layar awal ini dengan menambahkan ini ke styles.xmlfile Anda .

<item name="android:windowDisablePreview">true</item>

Namun menurut dokumentasi android hal ini dapat mengakibatkan waktu startup lebih lama. Cara yang disarankan untuk menghindari layar putih awal ini menurut google adalah dengan menggunakan windowBackgroundatribut tema aktivitas dan menyediakan drawable khusus sederhana untuk memulai aktivitas.

Seperti ini:

File Tata Letak yang Dapat Digambar, my_drawable.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
  <!-- The background color, preferably the same as your normal theme -->
  <item android:drawable="@android:color/white"/>
  <!-- Your product logo - 144dp color version of your app icon -->
  <item>
    <bitmap
      android:src="@drawable/product_logo_144dp"
      android:gravity="center"/>
  </item>
</layer-list>

Ciptakan gaya baru di styles.xml

<!-- Base application theme. -->
<style name="AppTheme">
    <!-- Customize your theme here. -->               
</style>

<!-- Starting activity theme -->
<style name="AppTheme.Launcher">
    <item name="android:windowBackground">@drawable/my_drawable</item>
</style>

Tambahkan tema ini ke aktivitas awal Anda di file Manifest

<activity ...
android:theme="@style/AppTheme.Launcher" />

Dan ketika Anda ingin beralih kembali ke panggilan tema normal Anda setTheme(R.style.Apptheme)sebelum menelepon super.onCreate()dansetContentView()

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // Make sure this is before calling super.onCreate
    setTheme(R.style.Theme_MyApp);
    super.onCreate(savedInstanceState);
    // ...
  }
}

Ini adalah cara yang disarankan untuk memecahkan masalah dan ini dari pola Desain Material google .


14

Sudahkah Anda mencoba menyetel android:windowBackgroundatribut dalam tema aktivitas peluncur Anda, ke warna atau drawable?

Contohnya begini:

<item name="android:windowBackground">@android:color/black</item>

ketika ditambahkan ke peluncur, tema aktivitas akan menampilkan warna hitam (bukan warna putih) saat memulai. Ini adalah trik mudah untuk menyembunyikan inisialisasi yang lama, sambil menunjukkan sesuatu kepada pengguna Anda, dan ini berfungsi dengan baik bahkan jika Anda membuat subkelas objek Application.

Hindari menggunakan konstruksi lain (bahkan Thread) untuk melakukan tugas-tugas inisialisasi yang lama, karena Anda mungkin akhirnya tidak dapat mengontrol siklus proses konstruksi tersebut. Objek Application adalah tempat yang tepat untuk melakukan persis jenis tindakan ini.


14

Saya menambahkan dua baris berikut dalam tema saya di bawah styles.xml

    <item name="android:windowDisablePreview">true</item>
    <item name="android:windowBackground">@null</item>

Bekerja seperti pesona


10

Saya memiliki masalah yang sama, Anda harus memperbarui gaya Anda.

style.xml

<!-- Base application theme. -->
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

        <!-- Customize your theme here. -->
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowDisablePreview">true</item>
        <item name="android:windowBackground">@null</item>
        <item name="android:windowIsTranslucent">true</item>

 </style>

File manifes Anda akan terlihat seperti di bawah ini.

<application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
     // Other stuff
</application>

Keluar keluar:

masukkan deskripsi gambar di sini

Semoga ini bisa membantu Anda.


2
Itu berfungsi dengan baik untuk saya pada aplikasi NativeActivity OpenGL. Saya tidak yakin mengapa ini tidak lebih tinggi dalam jawaban karena ini adalah jawaban yang paling lengkap dan bijaksana. Tidak ada Java yang melibatkan hanya beberapa perubahan file XML.
Slion

7

Dalam metode callback daur hidup, Anda bisa mendeklarasikan bagaimana aktivitas Anda berperilaku saat pengguna keluar dan masuk kembali ke aktivitas. Ingatlah bahwa cara Android dirancang, ada siklus proses untuk setiap aplikasi. Jika Anda memasukkan terlalu banyak beban ke onCreate()metode (yang merupakan metode yang digunakan untuk memuat file tata letak dan mengaktifkan kontrol yang Anda miliki di dalamnya), maka layar putih akan menjadi lebih terlihat, karena file tata letak akan membutuhkan waktu lebih lama untuk dimuat.

Saya menyarankan menggunakan beberapa metode berbeda saat memulai suatu kegiatan. Itulah onStart()(dipanggil sebagai hal pertama setelah aplikasi dimuat), onActivityCreated()(dipanggil setelah tata letak ditampilkan dan berguna jika Anda membuat pemrosesan data apa pun saat memulai aktivitas).

Untuk memudahkan Anda, di bawah ini adalah diagram siklus hidup aktivitas resmi:

masukkan deskripsi gambar di sini


Terima kasih atas jawaban Anda, sangat menarik. Namun, saya yakin Anda salah memahami pertanyaan saya. Masalahnya bukan disebabkan oleh inisialisasi yang pertama Activity, tetapi pada Applicationobjek global . Dan saya tidak percaya saya dapat menerapkan pemisahan masalah seperti Activityitu di sana, karena tidak seperti itu, ia hanya memiliki onCreate()metode.
YS

Mengapa Anda memperluas kelas aplikasi dan bukan aktivitasnya?
Michele La Ferla

Oke, jadi maksud Anda saya harus meninggalkan Applicationobjek sama sekali dan memindahkan semua kode inisialisasi ke yang pertama Activity...
YS

Begitulah cara saya selalu mengembangkan aplikasi saya, namun jika Anda tidak ingin melakukan semua perubahan itu, jawaban lain mungkin membantu Anda mengatasi masalah Anda menggunakan kelas aplikasi. Untuk referensi Anda di masa mendatang, saya sarankan untuk segera menggunakan satu kelas aktivitas, lalu banyak fragmen. Semoga ini bisa membantu :)
Michele La Ferla

2

Apakah Anda mencoba melakukan inisialisasi onActivityCreated?

Di dalam Applicationkelas:

 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                if(activity.getClass().equals(FirstActivity.class) {
                    // try without runOnUiThread if it will not help
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            new InitializatioTask().execute();
                        }
                    });
                }
            }

            @Override
            public void onActivityStarted(Activity activity) {

            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {

            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });

2

Seperti yang sudah Anda ketahui mengapa layar putih ini ada, karena proses latar belakang atau inisialisasi aplikasi atau file besar, jadi periksa saja ide di bawah ini untuk mengatasi hal ini.

Untuk mencegah layar putih ini di awal aplikasi, salah satu caranya adalah layar splash, ini hanya cara yang belum final dan Anda harus menggunakannya.

Ketika Anda akan menampilkan layar splash dari file splash.xml Anda, maka masalah ini juga akan tetap sama,

Jadi Anda harus membuat gaya ont dalam file style.xml untuk layar splash dan di sana Anda harus mengatur latar belakang jendela sebagai gambar splash Anda dan kemudian menerapkan tema itu ke aktivitas splash Anda dari file manifes. Jadi sekarang ketika Anda akan menjalankan aplikasi, pertama-tama itu akan mengatur tema dan dengan cara ini pengguna akan dapat melihat gambar percikan secara langsung, bukan layar putih.


2

Kedua properti itu berfungsi

    <style name="AppBaseThemeDark" parent="@style/Theme.AppCompat">
            <!--your other properties -->
            <!--<item name="android:windowDisablePreview">true</item>-->
            <item name="android:windowBackground">@null</item>
            <!--your other properties -->
    </style>

2

Silakan coba ini sekali.

1) Buat file splash_background.xml yang dapat digambar

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

    <item android:drawable="@color/{your color}" />

    <item>
        <bitmap
            android:layout_width="@dimen/size_250"
            android:layout_height="@dimen/size_100"
            android:gravity="center"
            android:scaleType="fitXY"
            android:src="{your image}"
            android:tint="@color/colorPrimary" />
    </item>

</layer-list>

2) Taruh ini di styles.xml

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

3) Di AndroidMainfest.xml Anda, setel tema di atas ke aktivitas Launch.

       <activity
            android:name=".SplashScreenActivity"
            android:screenOrientation="portrait"
            android:theme="@style/SplashTheme"
            android:windowSoftInputMode="stateVisible|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

0

Cukup tulis item di values ​​/ styles.xml:

<item name="android:windowBackground">@android:color/black</item>

Misalnya, di AppTheme:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>

    <item name="android:windowBackground">@android:color/black</item>

    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

0
Style :- 
<style name="SplashViewTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/splash</item>
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

In Manifest :- 
<activity android:name=".SplashActivity"
        android:theme="@style/SplashViewTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

0

Bagi siapa pun yang memiliki layar putih tersebut saat men-debug, ketahuilah bahwa jika Anda men-debug, pemuatan akan memakan waktu lebih lama. Jika Anda membuat APK rilis dan menginstalnya di ponsel, Anda akan melihat bahwa dibutuhkan lebih sedikit waktu untuk memuat.

Jadi waktu startup dengan versi debbug tidak sama dengan waktu startup dengan versi rilis.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.