Как избежать черного экрана при запуске, когда установлен FLAG_ACTIVITY_CLEAR_TASK?

Я запускаю новую активность, используя следующее:

Intent intent = new Intent(this, MyNewActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
overridePendingTransition(0, 0);

Во время запуска MyNewActivity отображается черный экран.

Если я удаляю Intent.FLAG_ACTIVITY_CLEAR_TASK, активность запускается без отображения черного экрана в любой момент (вместо этого отображается предыдущая активность, пока загружается новая).

Есть ли способ избежать этого черного экрана? Удаление флагов, похоже, не вариант (мне нужно очистить весь стек текущей задачи и запустить новую активность как корневую).

EDIT: я прилагаю очень простой код, который воспроизводит проблему (установите темную тему, например Theme.AppCompat для приложения). Черный экран показывается очень недолго (зависит от того, сколько работы проделывает принимающая активность при запуске), но увидеть его можно. Если вы не используете FLAG_ACTIVITY_CLEAR_TASK, черный экран не отображается и переход плавный:

Основное действие

public class MainActivity extends ActionBarActivity {

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

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MyNewActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
                overridePendingTransition(0,0);
            }
        });
    }
}

Моя новая активность

public class MyNewActivity extends ActionBarActivity {

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

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_bright">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CLICK ME!" />

</RelativeLayout>

activity_new.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_light">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I am the new activity!" />

</RelativeLayout>

Спасибо!


person Ereza    schedule 12.03.2015    source источник
comment
Исправьте свое приложение, чтобы оно мало что делало в onCreate(). Вместо этого разгрузите материал в фоновом потоке, который вы запускаете в onCreate().   -  person David Wasser    schedule 12.03.2015
comment
К сожалению, я больше не могу оптимизировать его (у приложения есть некоторые особые рекомендации по визуальному дизайну, которые требуют некоторой обработки фоновых изображений в основном потоке). В любом случае проблема не в этом. Я прикрепил пример кода, чтобы воспроизвести его в любом проекте, даже с активностью, которая ничего не делает.   -  person Ereza    schedule 13.03.2015
comment
Другой вариант — использовать Intent.FLAG_ACTIVITY_CLEAR_TOP вместо CLEAR_TASK. Это будет работать только в том случае, если вы оставите исходный экземпляр MyNewActivity в стеке (т.е. не закончите его при запуске других действий). Если это все еще не помогает, вы можете попробовать Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP. Это удалит все остальные действия из стека и вернет существующий экземпляр MyNewActivity. В этом случае вы можете добавить к Intent дополнительный элемент, который MyNewActivity может регистрировать в onNewIntent(), и если он установлен, он может повторно инициализировать себя.   -  person David Wasser    schedule 13.03.2015
comment
Я уже проверил другие режимы запуска Intent, FLAG_ACTIVITY_CLEAR_TOP в моем случае бесполезен, так как я бы никогда не запустил MyNewActivity, и я хочу очистить весь предыдущий стек активности. Например, у меня есть следующий поток: A-›B-›C-›D-›MyNewActivity Я хочу стереть из стека действий действия A, B, C и D и запустить MyNewActivity. Единственный флаг, который делает то, что я хочу, это Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK. По крайней мере, это единственное, о чем я знаю.   -  person Ereza    schedule 13.03.2015
comment
Вы должны удалить FLAG_ACTIVITY_CLEAR_TASK и вместо этого вызвать finish() после начала новой активности. эта ссылка мне очень помогла .   -  person Mehran Zamani    schedule 23.09.2017


Ответы (1)


Чтобы полностью избежать «черного экрана» (также известного как «предварительный просмотр»), вы можете добавить следующее в свой AppTheme:

<style name="AppTheme" parent="Theme.AppCompat">
    <item name="android:windowDisablePreview">true</item>
    ...
</style>

Однако лучший подход — делать меньше действий в основном потоке во время Activity.onCreate и позволить показывать экран предварительного просмотра, пока пользователь ждет. Для плавного перехода вы можете установить собственный фон для своих окон, добавив его в свою тему:

<style name="AppTheme" parent="Theme.AppCompat">
    <item name="android:windowBackground">@drawable/slash_screen</item>
    ...
</style>
person Francesco Vadicamo    schedule 03.08.2015
comment
Большое спасибо! Я никогда не думал, что то, что отображается, было предварительным просмотром! - person Ereza; 05.08.2015