Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: ErezaОтветов: 1

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

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>

Спасибо!

  • Исправьте свое приложение, чтобы оно мало что делало в onCreate(). Вместо этого разгрузите материал в фоновом потоке, который вы запускаете в onCreate(). David Wasser 12.03.2015
  • К сожалению, я больше не могу оптимизировать его (у приложения есть некоторые особые рекомендации по визуальному дизайну, которые требуют некоторой обработки фоновых изображений в основном потоке). В любом случае проблема не в этом. Я прикрепил пример кода, чтобы воспроизвести его в любом проекте, даже с активностью, которая ничего не делает. Ereza 13.03.2015
  • Другой вариант - использовать Intent.FLAG_ACTIVITY_CLEAR_TOP вместо CLEAR_TASK. Это будет работать только в том случае, если вы оставите исходный экземпляр MyNewActivity в стеке (т.е. не закончите его при запуске других действий). Если это все еще не помогает, вы можете попробовать Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP. Это удалит все остальные действия из стека и вернет существующий экземпляр MyNewActivity. В этом случае вы можете добавить к Intent дополнительный элемент, который MyNewActivity может регистрировать в onNewIntent(), и если он установлен, он может. David Wasser 13.03.2015
  • Я уже проверил другие режимы запуска 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. По крайней мере, это единственное, о чем я знаю. Ereza 13.03.2015
  • Вы должны удалить FLAG_ACTIVITY_CLEAR_TASK и вместо этого вызвать finish() после начала новой активности. эта ссылка мне очень помогла . Mehran Zamani 23.09.2017

androidandroid-activityandroid-intentflags

Ответы

Ответ 1 · рейтинг 23 · Francesco Vadicamo

Чтобы полностью избежать "черного экрана" (также известного как "предварительный просмотр"), вы можете добавить следующее в свой 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>

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы