Делаем экран загрузки Android приложения правильно

Original author: Chris Stewart
  • Translation
  • Tutorial
Splash Screen (прим.: тут и далее — экран загрузки) просто отнимает ваше время, верно? Как Android разработчик, когда я вижу экран загрузки, я тут же представляю как некоторые плохие разработчики добавляют трехсекундную задержку в коде.

Я должен смотреть на какое-то изображение в течении нескольких секунд, и до тех пор я не могу использовать приложение. И я должен это делать каждый раз после запуска приложения. Я знаю какое приложение я запустил. Я знаю что оно делает. Просто позвольте мне использовать его!

Что рекомендует Google


Вы будете удивлены, узнав что сторонники Google используют Splash Screen. Это описано прямо вот тут, в спецификации к Material Design.

Так было не всегда. Google был против Splash Screen, и даже назвал его анти-паттерном.

image


Что же я вижу?

Правильный Splash Screen


Я считаю, что Google не противоречит сам себе. Старый совет и новые рекомендации хорошо сочетаются. (Тем не менее, все-таки не очень хорошая идея использовать экран загрузки который отнимает время пользователя. Пожалуйста, не делайте так)

Однако, Android приложениям требуется некоторое количество времени для запуска, особенно при холодном запуске. Существует задержка которую вы не можете избежать. Вместо того чтобы показывать пустой экран, почему бы не показать пользователю что-то хорошее? Именно за этот подход Google и выступает. Не стоит тратить время пользователя, но не показывайте ему пустой, ненастроенный раздел приложения, когда он запускает его впервые.

Если вы посмотрите на последние обновления Google приложений, вы увидите подобный способ использования экрана загрузки. Например, взгляните на приложение YouTube:

image


Количество времени, которые вы тратите на просмотр Splash Screen, точно соответствует количеству времени, которое требуется приложению для запуска. При холодном запуске, это означает что Splash Screen будет виден дольше. А если приложение уже закэшировано, заставка исчезнет почти сразу.

Реализация Splash Screen



Реализация Splash Screen правильным способом немного отличается от того что вы можете себе приставить. Представление Splash Screen, который вы видите, должно быть готово немедленно, даже прежде чем вы можете раздуть (прим.: inflate) файл макета в вашей Splash Activity (прим.: Activity — активность, деятельность).

Поэтому мы не будем использовать файл макета. Вместо этого мы укажем фон нашего Splash Screen в фоне темы своей Activity. Для этого, сначала необходимо создать XML drawable в res/drawable.

Примечание: весь код ниже доступен на GitHub.

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

    <item
        android:drawable="@color/gray"/>

    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

Здесь я задал цвет фона и изображение.

Дальше, вы должны установить этот drawable в качестве фона для темы вашего Splash Screen Activity. Перейдите в файл styles.xml и добавьте новую тему для Splash Screen Activity:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

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

В вашей новой SplashTheme установите в качестве фона ваш XML drawable. И установите эту тему в своей Splash Screen Activity в вашем AndroidManifest.xml:

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

И, наконец, ваш класс SplashActivity должен перенаправить вас в ваше основное Activity:

public class SplashActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

Обратите внимание, что вы не настраивает вид для SplashActivity. Представление берется непосредственно из темы. Когда вы задаете вид вашей Splash Screen Activity через тему, он доступен немедленно.

Если у вас есть файл макета для вашей Splash Activity, он будет показан только после того как ваше приложение будет полностью инициализировано, а это что очень поздно. Ведь мы хотим чтобы Splash Screen отображался только небольшой промежуток времени, до того как приложение будет инициализировано.

Делаем это правильно


Как только шаги выше завершены, вы получите Splash Screen реализованный правильным путем:

image


Вооруженные этим знанием, заставьте ваш Splash Screen работать правильно. Не тратьте время пользователей попусту, но дайте им то, на что им будет приятно смотреть пока они ждут.

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 17

    +1
    Ненавижу splash screen 2гиса, особенно когда я за рулём )
      0
      Там скорее дело не в самом splash screen, а в том, что он показывается очень долго даже на мощных смартфонах — просо потому что приложение долго грузится. =(
        0
        Может, там стоит задержка? Сам не пользуюсь, не знаю.
        Было время, еще до того, как Google начал использовать Splash Screen в своих приложениях, я делал Android версию одного приложения для iOS. Ну и заказчик требовал, чтоб приложение показывало Splash Screen в начале, «ведь в iOS оно есть!!!». Пришлось сделать задержку в пару секунд, так как приложение грузилось быстро даже на слабых телефонах.
          +2
          ну, надо было показать Apple HIG этому заказчику. На всех WWDC инженеры со сцены умоляют не делать именно Splash скрины. У Launch Screen в iOS совсем другая задача. Они должны сделать вид, что ваше приложение наоборот загружается настолько быстро, что моментально показывает элементы реального экрана, который появится после загрузки. Вот, что дословно говорит нам HIG

          A launch screen appears instantly when your app starts up. The launch screen is quickly replaced with the first screen of your app, giving the impression that your app is fast and responsive. The launch screen isn’t an opportunity for artistic expression. It’s solely intended to enhance the perception of your app as quick to launch and immediately ready for use. Every app must supply a launch screen.
          0
          ~1 сек. на Nexus 5. Может я чего-то не понимаю, но имхо, это оптимальное время для splash screen.
        0
        Splash screen может служить для загрузки данных или же для аптейда токена, и что значит правильно? каждый делает как удобно, поставить таймер, хэндлер на 2с я не вижу прям какой то опаски над этим. Тем более сплеш может быть анимация или видео.
          +2
          Ну как-же. опаска в том что в будущем реально будет грузится за 0.2, но пользователи все равно будут ждать чертовые 2 секунды каждый раз.
          +1
          Спасибо за статью! Не мог найти, как избавиться от белого экрана на старте приложения. Теперь все гуд=).
            +2
            Как обычно — начали «за здравие», кончили — «за упокой». Сделать потомок основной темы с кастомным drawable — будь то лого или что-либо другое — это «за здравие». Применять эту тему к абсолютно лишнему активити, которое более никаких функций не выполняет, и ставить это никому не нужное активити ланчером — это «за упокой». Зачем городить огород, ведь запуск пусть и пустого активити, которое только и делает, что редиректит на основное (которое и должно быть ланчером), в любом случае занимает какое-то время и ресурсы.
            Теперь — действительно правильный вариант. Стартовую тему, которая показывает лого, или что-нибудь иное, что-бы пользователь не видел белый экран, — нужно применять к ОСНОВНОМУ активити вашего приложения, у которого интент-фильтр настроен как
                        <intent-filter>
                            <action android:name="android.intent.action.MAIN" />
            
                            <category android:name="android.intent.category.LAUNCHER" />
                        </intent-filter>
            

            Если у вас в этом активити используется разметка, у которой есть свой фон, который полностью закрывает экран — этого уже достаточно. Если же нет, то поменять тему программно — проще простого — первой же строчкой в onCreate (не обязательно именно первой, но сделать это необходимо до вызова super.onCreate):
                protected void onCreate(Bundle savedInstanceState) {
                    setTheme(R.style.AppTheme_NoActionBar);
                    ...
                }
            

            P.S. Данную статью в оригинале я читал где-то год назад. И где-то в то же время действительно правильное решение гуглилось на stackoverflow уже тогда (второй ответ, а не тот, который с галочкой). И там же ссылка на пост-источник с правильным решением. Вот этот пост и нужно было переводить.
              0
              Ваш пример не рабочий, более того — он ломает основной стиль приложения
                0
                Аргументы будут, или так, просто дабы ляпнуть что-нибудь? В моих приложения все отлично работает.
                  0
                  У меня, ваш пример тоже «работает», но в пол силы, у меня есть догадки почему он работает так, как не ожидается, но это только догадки, по факту выполнив ваши инструкции полностью я получил сплэш, потом мэайн активити с поломанными стилями приложения, и кстати в скорости загрузки от вашего способа профита нету, по крайней мере ощутимого точно, а вот не приятные последствия — да
                    0
                    Аргументы таки отсутствуют, ибо если бы они были, то было бы указано — сломалось то-то, не работает это. А так — это просто слова без подтверждения. Еще раз — у меня все ОК, у 4+ сотен пользователей stackoverflow, отметивших ответ как правильный — видимо тоже. Периферийное устройство «прямые руки» в наличии?
                      0
                      Я же сто раз уже написал что сломалось. Я не спорю, что способ может работать на уровне HelloWord — идеально, но при интеграции в реальный проект это ломает существующие стили. Вам скрин прислать? Ну тогда это уже будут не аргумены, а факты) Если они вам нужны, то могу предоставить, без проблем). Да и overflow Вы, видимо не внимательно читали, советую пересмотреть
              0
              сам тоже польюзуюсь таким подходом, вот статья, где я это нашел — там в довес есть примеры с анимациями для красивых переходом Avoiding cold starts on Android
                +2
                Сплэш может быть идеальным местом для инициализации нативных библиотек.
                Я, например, сделал там инициализацию ретрофита, AndroidThreeTen и настройку Realm.
                  0
                  У кого он перестал работать в Android 8 и 9? Приложение просто не открывается, пришлось отказаться.

                  Only users with full accounts can post comments. Log in, please.