Android - Ngăn chặn màn hình trắng khi khởi động


110

Như chúng ta đã biết, nhiều ứng dụng Android hiển thị màn hình trắng rất nhanh trước khi xuất hiện lần đầu tiên Activity. Vấn đề này được quan sát trong các trường hợp sau:

  • Các ứng dụng Android mở rộng phạm vi toàn cầu Applicationvà thực hiện các bước khởi tạo lớn trong đó. Đối Application tượng luôn được tạo trước đối tượng đầu tiên Activity(một thực tế có thể được quan sát trong trình gỡ lỗi), vì vậy điều này có ý nghĩa. Đây là nguyên nhân gây ra sự chậm trễ trong trường hợp của tôi.

  • Các ứng dụng Android hiển thị cửa sổ xem trước mặc định trước màn hình giật gân.

Cài đặt android:windowDisablePreview = "true"rõ ràng không hoạt động ở đây. Tôi cũng không thể đặt chủ đề chính của màn hình giật gân thành Theme.Holo.NoActionBarnhư được mô tả ở đây , vì [rất tiếc] màn hình giật gân của tôi sử dụng một ActionBar.

Trong khi đó, các ứng dụng không mở rộng Applicationlớp sẽ không hiển thị màn hình trắng khi khởi động.

Vấn đề là, lý tưởng nhất là các lần khởi tạo được thực hiện trong Applicationđối tượng cần phải xảy ra trước khi lần đầu tiên Activityđược hiển thị. Vì vậy, câu hỏi của tôi là, làm thế nào tôi có thể thực hiện các khởi tạo này khi khởi động ứng dụng mà không sử dụng một Applicationđối tượng? Có thể sử dụng một Threadhoặc Service, tôi cho là?

Đây là một vấn đề thú vị để suy nghĩ. Tôi không thể bỏ qua nó theo cách thông thường (bằng cách đặt NoActionBarchủ đề), vì thật bi thảm là màn hình Splash của tôi thực sự có một ActionBarsố lý do không liên quan.

Ghi chú:

Tôi đã tham khảo các câu hỏi sau:

Người giới thiệu:


1
Bạn đã tự tìm thấy sự cố, bạn đang làm với nhiều init trong ngữ cảnh ứng dụng, chặn tải hoạt động, hãy thử không đồng bộ hóa điều này, để hoạt động tải hiển thị cho đến khi một số chuỗi kết thúc.
AxelH

Điều này có thể hữu ích
Tối đa

1
Lý tưởng nhất là một ứng dụng sẽ giảm tải quá trình xử lý và không sử dụng luồng chính cho các hoạt động dài. Đây là một thực tế được chấp nhận tốt. Nếu các hoạt động cần diễn ra trước khi ứng dụng tải, thì ít nhất nó phải không chia sẻ một chuỗi với giao diện người dùng.
Beshoy Hanna

1
Bạn có thể thấy rằng đây vẫn là một vấn đề sau khi bạn đã di chuyển tất cả mã khởi tạo ra khỏi Applicationlớp. Điều này là do các phiên bản mới hơn của cách "khởi động lạnh" các ứng dụng của Android. Google thực sự đã giải quyết thời gian ra mắt tại Google I / O năm nay và nó sẽ được ấn định thành N theo những gì tôi nhớ. Trong thời gian chờ đợi, bạn nên xem cái mà Google gọi là "màn hình khởi chạy có thương hiệu". Đây là một ví dụ về cách tạo nó: antonioleiva.com/branded-launch-screen - không còn màn hình trắng khi bắt đầu ;-) Và vui lòng không sử dụng các màn hình giật gân - nó gây khó chịu cho người dùng.
Darwind

1
Chủ đề Wrt, mẹo là không đặt chủ đề NoActionBar, mà là điều chỉnh chủ đề của hoạt động ban đầu để màn hình có chủ đề trống trông giống như màn hình được khởi tạo hoàn toàn.
zapl

Câu trả lời:


86

Sự cố với nền trắng là do android khởi động nguội khi ứng dụng tải vào bộ nhớ và có thể tránh được điều này:

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();
    }
}
}

bố trí

<?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>

khuôn mặt img

<?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>

Thêm chủ đề này vào màn hình giật gân của bạn trong tệp kê khai

<?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>

sẽ tạo ra sự hoàn hảo như thế này

một con mèo bận rộn

để biết thêm chi tiết và các giải pháp khác, bạn có thể kiểm tra BlogPost này


3
nó không giúp vẫn màn hình trắng và hình ảnh động ở cuối
Mehvish Ali

Đây là thực hiện thẳng về phía trước. Có thể có một số phần khác trong mã của bạn gây ra sự cố. Vui lòng mở một câu hỏi khác và tôi sẽ ở đó để giúp bạn :)
Ivan Milisavljevic

1
Tôi đã giải quyết vấn đề này bằng cách tạo hoạt ảnh giữa các chủ đề và thay đổi chủ đề mà không thể vẽ được mà chỉ có màu phía sau giống nhau và sau đó trên onWindowFocusChanged () làm nổi bật nội dung có thể nhìn thấy và hoạt ảnh khác khôn ngoan hơn của tôi giữa quá trình chuyển đổi. hoạt ảnh về các chủ đề đã giúp ích rất nhiều
Mehvish Ali

93

vui lòng thêm dòng này vào chủ đề ứng dụng của bạn

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

để biết thêm thông tin: https://developer.android.com/topic/performance/vitals/launch-time#themed


25
Nó treo ứng dụng trong 2 giây và sau đó khởi chạy ứng dụng, không hữu ích cho tôi!
Faakhir

4
grate bây giờ nó không hiển thị màu # FFFFFF nhưng bây giờ nó đang hiển thị # 000000
Midhilaj

@Faakhir Vậy bạn đã tìm ra giải pháp nào chưa? Tôi vẫn đang tìm kiếm một giải pháp, loại bỏ màn hình trắng này và cũng không có thời gian khởi chạy.
Rupam Das

33

Vui lòng sao chép và dán hai dòng này vào chủ đề ứng dụng tệp kê khai của bạn, tức là res / styles / AppTheme. sau đó nó sẽ hoạt động như quyến rũ ..

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

21

Trước hết, để loại bỏ màn hình trắng, hãy đọc phần này - https://www.bignerdranch.com/blog/splash-screens-the-right-way/

Nhưng quan trọng hơn, hãy tối ưu hóa tải ban đầu của bạn và hoãn mọi công việc nặng nhọc khi bạn có thời gian để chạy nó. Đăng lớp ứng dụng của bạn ở đây nếu bạn muốn chúng tôi xem xét nó.


20

Cách giải quyết vấn đề này được đề xuất còn thiếu trong các câu trả lời. Vì vậy, tôi đang thêm câu trả lời của tôi ở đây. Sự cố màn hình trắng khi khởi động xảy ra do màn hình trống ban đầu mà quy trình hệ thống vẽ khi khởi chạy ứng dụng. Một cách phổ biến để giải quyết vấn đề này là tắt màn hình ban đầu này bằng cách thêm nó vào styles.xmltệp của bạn .

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

Nhưng theo tài liệu Android, điều này có thể dẫn đến thời gian khởi động lâu hơn. Cách đề xuất để tránh màn hình trắng ban đầu này theo google là sử dụng windowBackgroundthuộc tính chủ đề của hoạt động và cung cấp một tùy chỉnh đơn giản có thể vẽ cho hoạt động bắt đầu.

Như thế này:

Tệp bố cục có thể vẽ, 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>

Tạo một phong cách mới trong 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>

Thêm chủ đề này vào hoạt động bắt đầu của bạn trong tệp kê khai

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

Và khi bạn muốn chuyển trở lại cuộc gọi chủ đề thông thường setTheme(R.style.Apptheme)trước khi gọi super.onCreate()setContentView()

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);
    // ...
  }
}

Đây là cách được khuyến nghị để giải quyết vấn đề và đây là từ google Material Design các mẫu.


14

Bạn đã thử đặt android:windowBackgroundthuộc tính trong chủ đề của hoạt động trình khởi chạy của mình thành màu hoặc có thể vẽ chưa?

Ví dụ điều này:

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

khi được thêm vào chủ đề hoạt động của Trình khởi chạy sẽ hiển thị màu đen (thay vì màu trắng) khi khởi động. Đây là một thủ thuật dễ dàng để ẩn quá trình khởi tạo dài, trong khi hiển thị cho người dùng của bạn điều gì đó và nó hoạt động tốt ngay cả khi bạn phân lớp đối tượng Ứng dụng.

Tránh sử dụng các cấu trúc khác (ngay cả Luồng) để thực hiện các tác vụ khởi tạo dài, bởi vì bạn có thể không kiểm soát được vòng đời của các cấu trúc đó. Đối tượng Ứng dụng là nơi thích hợp để thực hiện chính xác loại hành động này.


14

Tôi đã thêm hai dòng sau vào chủ đề của mình dưới styles.xml

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

Làm việc như người ở


10

Tôi đã gặp vấn đề tương tự, bạn phải cập nhật phong cách của mình.

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>

Tệp kê khai của bạn sẽ giống như bên dưới.

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

Ra ngoài:

nhập mô tả hình ảnh ở đây

Hy vọng điều này sẽ giúp bạn.


2
Điều đó rất hiệu quả đối với tôi trên ứng dụng NativeActivity OpenGL. Tôi không chắc tại sao điều này không cao hơn trong các câu trả lời vì nó là câu trả lời đầy đủ và thích hợp nhất. Không có Java chỉ liên quan đến một vài thay đổi tệp XML.
Slion

7

Trong các phương thức gọi lại vòng đời, bạn có thể khai báo cách hoạt động của mình hoạt động khi người dùng rời khỏi và tham gia lại hoạt động. Hãy nhớ rằng cách Android được thiết kế, có một vòng đời cho mỗi và mọi ứng dụng. Nếu bạn đặt quá nhiều tải cho onCreate()phương thức (là phương pháp được sử dụng để tải các tệp bố cục và kích hoạt bất kỳ điều khiển nào bạn có trong đó), thì màn hình trắng sẽ hiển thị nhiều hơn, vì tệp bố cục sẽ mất nhiều thời gian hơn để tải.

Tôi đề nghị sử dụng một số phương pháp khác nhau khi bắt đầu một hoạt động. Đó là onStart()(được gọi là thứ đầu tiên khi ứng dụng được tải), onActivityCreated()(được gọi sau khi bố cục được hiển thị và hữu ích nếu bạn đang thực hiện bất kỳ xử lý dữ liệu nào khi bắt đầu hoạt động).

Để giúp bạn dễ dàng hơn, dưới đây là sơ đồ vòng đời hoạt động chính thức:

nhập mô tả hình ảnh ở đây


Cảm ơn bạn đã trả lời, nó rất thú vị. Tuy nhiên, tôi tin rằng bạn đã hiểu sai câu hỏi của tôi. Vấn đề không phải do các lần khởi tạo trong lần đầu tiên Activity, mà là các lần khởi tạo trong Applicationđối tượng toàn cục . Và tôi không tin rằng tôi có thể áp dụng sự tách biệt các mối quan tâm như vậy ở đó, bởi vì không giống như một, Activitynó chỉ có một onCreate()phương pháp.
YS

Tại sao bạn mở rộng lớp ứng dụng chứ không phải lớp hoạt động?
Michele La Ferla

Được rồi, vì vậy bạn có nghĩa là tôi nên từ bỏ Applicationđối tượng hoàn toàn và di chuyển tất cả các mã khởi tạo để là người đầu tiên Activity...
YS

Đó là cách tôi luôn phát triển ứng dụng của mình, tuy nhiên nếu bạn không muốn thực hiện tất cả những thay đổi đó, các câu trả lời khác có thể giúp bạn giải quyết vấn đề của mình bằng cách sử dụng lớp ứng dụng. Để bạn tham khảo trong tương lai, tôi khuyên bạn nên sử dụng ngay một lớp hoạt động, sau đó sử dụng nhiều phân đoạn. Hy vọng điều này sẽ giúp :)
Michele La Ferla

2

Bạn đã thử đặt khởi tạo cho onActivityCreated?

ApplicationLớp bên trong :

 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

Như bạn đã biết tại sao lại xuất hiện màn hình trắng này, do quá trình chạy nền hoặc khởi tạo ứng dụng hoặc tệp lớn, vì vậy chỉ cần kiểm tra ý tưởng bên dưới để khắc phục điều này.

Để ngăn chặn màn hình trắng này khi bắt đầu ứng dụng, một trong những cách là màn hình giật gân, đây chỉ là cách không phải là cuối cùng và bạn phải sử dụng.

Khi bạn sẽ hiển thị màn hình giật gân từ tệp tin splash.xml của mình, thì vấn đề này cũng sẽ không thay đổi,

Vì vậy, bạn phải tạo kiểu ont trong tệp style.xml cho màn hình giật gân và ở đó bạn phải đặt nền cửa sổ làm hình ảnh giật gân và sau đó áp dụng chủ đề đó cho hoạt động giật gân của bạn từ tệp kê khai. Vì vậy, bây giờ khi bạn chạy ứng dụng, đầu tiên nó sẽ thiết lập chủ đề và bằng cách này, người dùng sẽ có thể nhìn thấy hình ảnh giật gân trực tiếp thay vì màn hình trắng.


2

Cả hai thuộc tính đều hoạt động

    <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

Hãy thử điều này một lần.

1) Xếp một tệp có thể vẽ được splash_background.xml

<?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) Đặt cái này vào styles.xml

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

3) Trong AndroidMainfest.xml của bạn, hãy đặt chủ đề trên thành Khởi chạy hoạt động.

       <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

Chỉ cần viết mục trong giá trị / styles.xml:

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

Ví dụ, trong 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

Đối với bất kỳ ai gặp phải màn hình trắng đó trong khi gỡ lỗi, hãy lưu ý rằng nếu bạn đang gỡ lỗi, sẽ mất nhiều thời gian hơn để tải. Nếu bạn tạo APK phát hành của mình và cài đặt nó trên điện thoại của mình, bạn sẽ nhận thấy rằng thời gian tải ít hơn rất nhiều.

Vì vậy, thời gian khởi động với phiên bản gỡ lỗi không bằng thời gian khởi động với phiên bản phát hành.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.