- 🕐 Revisited — 📚 A Guide on Splash Screen in Android in 2020
- 👀 A fresh look on the splash screen in Android in Kotlin and Coroutines
- 🎨 Using Activity Theme
- ⏰ Using Handler / Runnable / Timer
- 🎯 Using Kotlin Coroutines
- 💻 Show Me The Code
- wajahatkarim3/SplashScreen
- github.com
- 📄 Making The Decision
- Add Push Notifications to Your Android Chat App Using Kotlin
- November 24, 2019
- 🚀 Launching Activities in Easier Way Using Kotlin Extensions 💻
- March 4, 2019
- Полное руководство по Splash Screen на Android
- Два вида Splash Screen
- Placeholder не работает даже у приложений от Google
- Как работать с Branded launch screen
- Используя Launcher Theme
- Splash Screen в отдельной Activity c использованием Launcher Theme
- Используя таймеры
- Используя умные таймеры.
🕐 Revisited — 📚 A Guide on Splash Screen in Android in 2020
👀 A fresh look on the splash screen in Android in Kotlin and Coroutines
Splash screen is a very popular methodology in Android app development. Almost all major apps contain some sort of splash screen for many different reasons from brand awareness to loading heavy resources before app start. Some apps even add splash screens just because everyone else is adding it to follow the paradigm, even though their apps don’t need it.
Its a very debatable topic on whether apps should contain splash screen or not as this wastes few (important) seconds of user’s time. In this article, we will not be focusing on that debate. Rather, this topic is about technical details on creating splash screens with the modern Android development approaches followed in 2019 or upcoming 2020. So, without further ado, let’s start ordering from the old way to new way.
🎨 Using Activity Theme
When any app is launched, Android system will try to draw the first screen as fast as it can. But for the new launches, this may take few moments. During these moments, Android by default shows a empty placeholder screen filled with your app’s windowBackground color. You can extend this placeholder from just a color to your splash screen using the Activity theme approach.
Create a separate theme for your splash Activity and set its windowBackground to your custom splash drawable.
You can see that we have set windowBackground to our splash screen drawable in file splash_drawable.xml file. Here’s that file.
Now, set this theme to your splash Activity in the AndroidManifest.xml file.
And this will give you an Amazon-like splash screen.
Now, whatever time Android System is supposed to show a black placeholder screen while starting up your app and allocating memory resources for it, the system will show this screen instead of that placeholder. And once your app is ready and launched, then still you will be seeing this. And your whole layout passed in setContentView() method will be drawn on top of this screen. So, you will have to reset your original app’s theme in your Activity . You can do this easily by adding setTheme() before the setContentView() method call in your Activity class.
Now, as your app’s ready, it will change to your original app’s theme like the normal apps do. The code for this approach is available in the SplashThemeActivity class at the Splash Screen Demo repository.
Overall, this approach is good from the user experience as it doesn’t waste time. It only takes time to load the app. So, if your app is already in the memory, you won’t see the splash theme much. This approach is applied in Google’s apps a lot.
But the problems with this approach are that if your splash contains fancy animations or even a simple loading progress bar, you can’t add this. You can only add an image through tag in your theme and change the position of it on the screen.
If you want to add multiple starting points based on some logic, like whether to show login or the home screen, then this approach can work a little trick. Instead of setting splash theme to your home screen, create a separate dedicated Activity for your splash and apply the theme to it. Then write your business logic in that Activity . You can check the the code in SplashLogicActivity.kt class at the Splash Screen Demo repository.
⏰ Using Handler / Runnable / Timer
A huge number of apps follow this approach to create splash screen. The idea is to create a separate Activity for splash screen and then launch the main screen either fixed or based on some logic after some scheduled time of like 2–3 seconds. This splash screen doesn’t do anything except show the user some screen and make user wait for few seconds. This is achieved by commonly using the Handler and Runnable classes.
This is quite similar to the separate Activity with the theme approach. But we get many advantages in this method over the themed activity. You can add animations, or any sort of customizations in your layout for the splash screen. You can also add business logic to redirect user to any specific screen. But there’s a problem. The code for this is available in CommonSplashActivity at the Splash Screen demo repository.
If the user presses the hard back button while splash screen, it won’t cancel the Handler instance, and you will see some screen popup randomly because it was scheduled to launch. This can cause memory leak or if you’re storing some data in memory in your splash screen, then that data will be lost. Because Android system will launch your home screen as a new task.
One way to fix this is using the Timer class because we can cancel the Timer instance in either onPause() or onDestroy() methods to stop the scheduled launch of the home / login screens. You can get check this code in TimerSplashActivity at the Splash Screen demo repository.
This approach will avoid you the memory leaks or the sudden popping up of the screen because timer is cancelled in onPause() and because of it the launch of home screen task is also terminated.
It must be noted that Timer creates a whole new thread in background. And you cannot interact with UI elements, View objects etc. in this thread. For example, you cannot update animations of views, or change TextView ‘s text values etc in the TimerTask object. Memory-wise this is a heavy operation approach and due to thread-switching it can also be slow.
I have seen some places where a Thread is used instead of timer. And Thread.sleep() is used for delay purposes. I would highly recommend you to avoid this method as this will not only cause memory leaks and is almost similar to the previous Handler approach we discussed.
🎯 Using Kotlin Coroutines
Yes, you read that right. I would only recommend this method if you already have Kotlin Coroutines in your project or you plan to add in near future. Because it wouldn’t be a good approach to just add Kotlin Coroutines for splash screen.
Conceptually, this is a lot similar to Timer approach, but we will use coroutines, instead of Timer objects. Here’s the code for this. (You can also check this code in the SplashActivity in the Splash Screen repository on Github.
Since the activityScope we created is of Dispatchers.Main , so this will run on the main UI thread. And being a coroutine, there will be no thread switching as coroutines run on the same thread. This will help in the performance speed as opposed to the Timer approach.
As the Activity gets paused or destroyed, the coroutine will be cancelled automatically. This will avoid the sudden popping of the home/login screen. And surprisingly, since this coroutine is running on Dispatchers.Main , we can easily update UI elements, view animations etc. without any tension.
Overall, the coroutines approach is fast, reliable, less-memory consuming, gives the advantage of main UI thread access, and supports the custom launch logic.
💻 Show Me The Code
The code is available on my Github profile at Splash Screen repository. It contains all the splash screen approaches discussed in this article in separate Activity classes. You need to launch any of the Activity as launcher in AndroidManifest.xml to check the behavior of that approach.
wajahatkarim3/SplashScreen
A demo project showcasing different methods to create splash screen in Android and discusses the det.
github.com
📄 Making The Decision
The best approaches are theme approach and coroutines approach.
If your app has fixed home screen, then use the splash theme on that home screen.
If your app needs business logic to decide the home screen, use the separate Activity with theme approach.
If your app has fancy animations and / or complex splash UI, then create a separate Activity and use Kotlin Coroutines. If your app doesn’t intend to use Coroutines, then you should switch it the the Handler approach, but be aware of the memory leaks.
Finally, do not use Timer , or Thread at all for splash screen and try to avoid Handler approach too.
If you liked this article, you can read my new articles below:
Add Push Notifications to Your Android Chat App Using Kotlin
This story was originally published with collaboration with CometChat Pro, and Alex Booker on their tutorials blog. For any kind of chat apps, notifications are the driver behind whole chat concept.
November 24, 2019
🚀 Launching Activities in Easier Way Using Kotlin Extensions 💻
Kotlin Extensions for simpler, easier and fun way of launching Activities in Android Reposted on my Medium profile. Few days ago, I was reading this awesome article by Elye about a Kotlin keyword reified .
March 4, 2019
7 years experience. 💻 Creator of various Open Source libraries on Android . 📝 Author of two technical books and 100+ articles on Android. 🎤 A passionate Public Speaker giving talks all over the world.
Источник
Полное руководство по Splash Screen на Android
Перевод статьи Elvis Chidera «The (Complete) Android Splash Screen Guide». Но для начала немного истории о проблеме Splash Screen на Android.
Два вида Splash Screen
Google в гайдлайнах Material Design представляет две концепции Splash Screen (или Launch Screen):
- Placeholder UI
- Branded launch screen
Placeholder UI — концепция для приложений, которые загружаются довольно быстро и не требуют показа перед запуском логотипов, красивых анимаций и прочих украшений. Суть в том, что во время холодного старта основной фон приложения, строка состояния, фон для панели инструментов уже раскрашиваются в цвета приложения, но до полной загрузки без контента. Такой подход, по мнению дизайнеров Google, позволяет более плавно с точки зрения пользователя переходить от момента запуска приложения к работе с ним.
Branded launch screen — собственно и есть то, что большинство разработчиков (по крайней мере Android-разработчиков), именуют Splash Screen. Это некоторый логотип, изображение, реже анимация, которые пользователь на короткое время видит во время старта приложения.
Теперь, прежде чем перейдем к переводу статьи Элвиса, которая рассказывает о Branded launch screen, немного о грустном в лагере поклонников Placeholder UI.
Placeholder не работает даже у приложений от Google
Не смотря на собственные гайдлайны, Google не смог реализовать подход Placeholder UI в собственных приложениях. Я навскидку выбрал три популярных приложения от Google, где по логике должен быть Placeholder UI, но он не работает. Показан переход от холодного старта к рабочему состоянию приложения:
Как видим, во время холодного старта загружается только фон приложения, панель инструментов и строка состояния — либо под цвет фона, либо случайного цвета (как в примере с Play Market).
Причины этому следующие:
- Сегодня хорошим тоном считается использовать Toolbar , как часть макета панели инструментов. Это дает много плюшек: реакция на прокрутку, анимации и т.д. Но вместе с тем, необходимо использовать тему NoActionBar . Это влияет на то, что цвета главной темы приложения не подгружаются при холодном старте.
- Проблема в библиотеке AppCompat. Даже если использовать обычный ActionBar для панели инструментов, мы будем наблюдать аналогичный эффект. Переход от @style/Theme.AppCompat.Light.DarkActionBar к @android:style/Theme.Material.Light.DarkActionBar лечит эту проблему, но, вероятно, приложения все еще рассчитаны на поддержку версий до Lollipop.
О подходе Placeholder UI все. Переходим к переводу статьи Элвиса.
Как работать с Branded launch screen
В прошлом в Android не рекомендовалось делать Splash Screen в приложениях. Не было смысла заставлять пользователя ждать n секунд, чтобы показать заставку. И несомненно, что никто не запускает приложение ради заставки (об этом ниже).
Предоставление пользователю контента должно быть вашим приоритетом №1
Когда в Material Design появился раздел под названием Launch Screen (Splash Screen), кто-то из команды Android опубликовал пост о том, как сделать Splash Screen правильно.
В этом посте я рассмотрю четыре основных способа реализации Splash Screen на Android:
- Используя Launcher Theme (Хорошо)
- Используя Launcher Theme с предопределенной для Splash Screen Activity (Сойдет)
- Используя таймеры (Timers) (Плохо)
- Используя умные таймеры (Smart Timers) (Ужасно)
Используя Launcher Theme
Когда ваше приложение запускается и оно еще не в памяти, может иметь место задержка между тем, когда пользователь нажал на запуск, и тем, когда у Activity вызвано onCreate() . Этот, так называемый «холодный старт» — лучшее время, чтобы показать ваш Splash Screen.
Во время «холодного старта» оконный менеджер пытается отрисовать placeholder UI, используя элементы из темы приложения (app theme), такие как windowBackground . И то, что показывает windowBackground по-умолчанию (обычно белый или черный фон), вы можете поменять на какой угодно drawable, создав тем самым свой Splash Screen. Этот способ показывает Splash Screen только там, где необходимо, и не замедляет пользователя.
Итак, вам необходимо создать кастомную тему, переопределив android:windowBackground , заменив использование стандартной темы на вашу перед вызовом super.onCreate в вашей Activity.
В этом примере, я предполагаю, что главная тема вашего приложения называется AppTheme, но если это не так, просто во всех местах замените AppTheme на имя главной темы вашего приложения.
Вы должны создать новую тему AppTheme.Launcher . Единственный элемент, который необходимо переопределить — это windowBackground . В файл styles.xml добавим:
При этом мы наследуем все остальные атрибуты главной темы AppTheme, используя ее название, как префикс для названия нашей темы Launcher.
Определяем drawable launch_screen . Хотя вы могли бы использовать простую картинку, но она будет растянута на весь экран. Вместо этого используем XML-файл:
Пропишите тему для Splash Screen в файле манифеста в вашей стартовой Activity:
Теперь нужно вернуть главную тему в стартовую Activity (если, конечно, мы не хотим, чтобы Splash Screen радовал нас и во время работы приложения)
Самый простой способ сделать это — это вызвать setTheme(R.style.AppTheme) до super.onCreate() и setContentView() :
Все. Вы можете узнать подробнее об этом подходе здесь.
Плюсы:
- Нет никакой специальной Activity для Splash Screen. Нет задержки времени как в том случае, если бы вы вызывали рабочую Activity из Activity для Splash Screen.
- Нет искусственных задержек — Splash Screen показывается только тогда, когда приложение загружается.
Минусы:
Я встречал три довольно распространенные жалобы на этот подход:
- Splash Screen показывается снова если Activity была убита системой и снова восстановлена. В большинстве случаев, этот совсем не проблема, но при желании, если использовать второй способ, этого можно избежать.
- Некоторым разработчикам необходимо, чтобы после запуска Splash Screen, пользователь попадал на разные Activity, в зависимости от каких-либо параметров. Опять же, для таких задач можно использовать второй способ, но иногда реализация такой промежуточной Activity довольно неряшлива.
- Невозможно загрузить тяжелые данные/компоненты, когда показывается Splash Screen. Хотя это плохая идея: загружать тяжелые данные или компоненты, пока стартует приложение (есть некоторые исключения, как, например, инициализация некоторых библиотек). Можно попробовать один из следующих подходов.
- Постарайтесь использовать метод ленивой загрузки, для своих компонентов/модулей/библиотек. За исключением компонентов, которые кровно необходимы для работы приложения, старайтесь ничего не загружать во время запуска приложения, а загружать, когда вам понадобится компонент, или грузите в фоновом потоке сразу после старта приложения. Сохраняйте onCreate() вашего приложения легким насколько это возможно.
- Используйте кэширование. За исключением той информации, которая быстро меняется, остальное лучше кэшировать. Когда пользователь снова обращается к вашему приложению, вы можете показать закэшированный контент, пока более свежий контент загружается.
Я думаю, что следует избегать таких вещей, как долгий Splash Screen, как ProgressDialog, которые заставляют пользователя просто смотреть на экран и не дают ему выполнить никакое действие.
Если ваше приложение подключается к сети, предположите, что все, что должно пойти не так, пойдет не так. Таким образом вы сможете создавать приложения для миллионов людей, которые все еще используют нестабильные соединения 2G и 3G
Splash Screen в отдельной Activity c использованием Launcher Theme
Этот способ базируется на первом способе. Он требует отдельной Activity для Splash Screen. Первые два шага пропускаем, они аналогичны первому способу.
Осталось создать Activity для Splash Screen и указать в манифесте для нее тему AppTheme.Launcher . Теперь отредактируем Activity так, чтобы она перенаправляла на другие страницы. Смотрим пример ниже:
Плюсы:
- Решает первые две проблемы у первого способа.
Минусы:
- Я видел, как подобная маршрутизация легко становится уродливой.
- Небольшая задержка между двумя Activity.
- Опасность забыть и начать делать длительные операции здесь.
Используя таймеры
Это старый добрый подход. Надо просто создать отдельную для Splash Screen Activity, которая будет показываться x секунд. Затем открыть подходящую Activity. Используя такой подход, вы получаете больше гибкости, потому что можете добавить анимацию, кастомные view или любые другие элементы, которые вы можете поместить в макет Activity. Вот минимальная реализация такого подхода:
Плюсы:
- Появляется возможность показать вашу супер-анимацию, или любой другой кастомный дизайн, который вы хотите. Это имеет смысл для игровых приложений или приложений для детей.
- Большая гибкость того, что вы можете показать на Splash Screen.
Минусы:
- Двойной удар — ваша Activity не стартовая Activity не появляется немедленно, после того, как приложение запущено, особенно во время холодного старта. Пользователь ждет во время холодного старта, наблюдая только windowBackground и, затем, просматривая еще Splash Screen до того, как запустится рабочая Activity.
- Ваша супер-анимация или дизайн обычно восхищает пользователя только первые пару раз. Потом, большинство пользователей находит его скучным, и они хотят получить только контент. Я думаю, что четвертый способ способен исправить это.
- В большинстве случаев дополнительная задержка неоправданна.
Используя умные таймеры.
Этот подход базируется на третьем способе. Но вместо постоянной задержки, вы запускаете Splash Screen или нет, основываясь на том, первый это запуск или нет. Вот пример, который использует SharedPreferences :
Плюсы:
- Это возможное решение проблемы, когда пользователь устает наблюдать ваш Splash Screen в течении долгого времени.
Минусы:
- Двойной удар — проблемы третьего способа все еще не здесь
- В большинстве случаев дополнительная задержка неоправданна.
- Я не использовал этот метод, но, думаю, может быть некоторая задержка при чтении из SharedPreferences .
Это все о Splash Screen. Если я что-то упустил, напишите в комментариях.
Следует заметить, что на Хабре уже была статья (перевод), где речь шла о Splash Screen. Однако затронутый там подход (соответствует второму способу в этой статье), как мы могли убедиться, не самый оптимальный для большинства случаев. Ну и последнее, в Android Oreo якобы добавлено Splash Screen API, что позволит разработчикам легко добавлять Splash Screen в свои приложения, но на данный момент в официальной документации по этому поводу никакой информации нет.
Источник