- Делаем экран загрузки Android приложения правильно
- Что рекомендует Google
- Правильный Splash Screen
- Реализация Splash Screen
- Делаем это правильно
- 🕐 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 screens in Android 12
- Summary
Делаем экран загрузки Android приложения правильно
Splash Screen (прим.: тут и далее — экран загрузки) просто отнимает ваше время, верно? Как Android разработчик, когда я вижу экран загрузки, я тут же представляю как некоторые плохие разработчики добавляют трехсекундную задержку в коде.
Я должен смотреть на какое-то изображение в течении нескольких секунд, и до тех пор я не могу использовать приложение. И я должен это делать каждый раз после запуска приложения. Я знаю какое приложение я запустил. Я знаю что оно делает. Просто позвольте мне использовать его!
Что рекомендует Google
Вы будете удивлены, узнав что сторонники Google используют Splash Screen. Это описано прямо вот тут, в спецификации к Material Design.
Так было не всегда. Google был против Splash Screen, и даже назвал его анти-паттерном.
Правильный Splash Screen
Я считаю, что Google не противоречит сам себе. Старый совет и новые рекомендации хорошо сочетаются. (Тем не менее, все-таки не очень хорошая идея использовать экран загрузки который отнимает время пользователя. Пожалуйста, не делайте так)
Однако, Android приложениям требуется некоторое количество времени для запуска, особенно при холодном запуске. Существует задержка которую вы не можете избежать. Вместо того чтобы показывать пустой экран, почему бы не показать пользователю что-то хорошее? Именно за этот подход Google и выступает. Не стоит тратить время пользователя, но не показывайте ему пустой, ненастроенный раздел приложения, когда он запускает его впервые.
Если вы посмотрите на последние обновления Google приложений, вы увидите подобный способ использования экрана загрузки. Например, взгляните на приложение YouTube:
Количество времени, которые вы тратите на просмотр Splash Screen, точно соответствует количеству времени, которое требуется приложению для запуска. При холодном запуске, это означает что Splash Screen будет виден дольше. А если приложение уже закэшировано, заставка исчезнет почти сразу.
Реализация Splash Screen
Реализация Splash Screen правильным способом немного отличается от того что вы можете себе приставить. Представление Splash Screen, который вы видите, должно быть готово немедленно, даже прежде чем вы можете раздуть (прим.: inflate) файл макета в вашей Splash Activity (прим.: Activity — активность, деятельность).
Поэтому мы не будем использовать файл макета. Вместо этого мы укажем фон нашего Splash Screen в фоне темы своей Activity. Для этого, сначала необходимо создать XML drawable в res/drawable.
Здесь я задал цвет фона и изображение.
Дальше, вы должны установить этот drawable в качестве фона для темы вашего Splash Screen Activity. Перейдите в файл styles.xml и добавьте новую тему для Splash Screen Activity:
В вашей новой SplashTheme установите в качестве фона ваш XML drawable. И установите эту тему в своей Splash Screen Activity в вашем AndroidManifest.xml:
И, наконец, ваш класс SplashActivity должен перенаправить вас в ваше основное Activity:
Обратите внимание, что вы не настраивает вид для SplashActivity. Представление берется непосредственно из темы. Когда вы задаете вид вашей Splash Screen Activity через тему, он доступен немедленно.
Если у вас есть файл макета для вашей Splash Activity, он будет показан только после того как ваше приложение будет полностью инициализировано, а это что очень поздно. Ведь мы хотим чтобы Splash Screen отображался только небольшой промежуток времени, до того как приложение будет инициализировано.
Делаем это правильно
Как только шаги выше завершены, вы получите Splash Screen реализованный правильным путем:
Вооруженные этим знанием, заставьте ваш Splash Screen работать правильно. Не тратьте время пользователей попусту, но дайте им то, на что им будет приятно смотреть пока они ждут.
Источник
🕐 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 screens in Android 12
2021-05-05: With dp3 apis and emulator images the splash screens now work as described. I have published a sample app on GitHub.
The Android 12 Developer Preview contains support for splash screens. Even though the api might change until the final release of Android 12, or the feature might even be removed again, it is interesting to see what we know at the moment.
Curious? Come, join me in my investigations.
First of all, there is a new interface android.window.SplashScreen . Currently the docs say:
The interface that apps use to talk to the splash screen.
Each splash screen instance is bound to a particular
Activity . To obtain a SplashScreen for an Activity ,
use Activity.getSplashScreen() to get the SplashScreen .
The interface contains one method: setOnExitAnimationListener()
Specifies whether an Activity wants to handle the splash
screen animation on its own. Normally the splash screen
will show on screen before the content of the activity has
been drawn, and disappear when the activity is showing on
the screen. With this listener set, the activity will
receive OnExitAnimationListener#onSplashScreenExit
callback if splash screen is showed, then the activity can
create its own exit animation based on the
SplashScreenView .
Note that this method must be called before splash screen
leave, so it only takes effect during or before
Activity#onResume .
Let’s try to see this in action. As SplashScreen is an interface it is interesting to see the actual implementation.
Exit fullscreen mode
If we run the code, D/MainActivity: —> android.window.SplashScreen$SplashScreenImpl is printed.
SplashScreenImpl is no public api class, still, we can look what it contains during runtime:
One of its properties, mGlobal , references a SplashScreenManagerGlobal . We don’t know much about this class, but peeking inside it reveals
so one of its properties holds an ArrayList of SplashScreenImpl objects.
While this is interesting, it doesn’t help with a major issue of my code: the second output ( Log.d(TAG, it::class.java.name) ) is not printed.
This means that the listener we set using setOnExitAnimationListener() is not invoked. Which is a pity, because the docs of SplashScreen.OnExitAnimationListener sound great. This interface defines one method, onSplashScreenExit(SplashScreenView view) .
When receiving this callback, the SplashScreenView object
will be drawing on top of the activity. The
SplashScreenView represents the splash screen view
object, developer can make an exit animation based on this
view.
So, what do we do?
Maybe it’s a timing issue, maybe the app is too fast.
Exit fullscreen mode
No, doesn’t help. Let’s think again.
Hasn’t splash screen support been built into Android since api level 26 (Oreo)?
android.R.attr contains windowSplashscreenContent . The docs say:
Reference to a drawable to be used as the splash screen
content of the window. This drawable will be placed on top
of the windowBackground with its bounds inset by the
system bars. If the drawable should not be inset by the
system bars, use a fullscreen theme.
In your themes.xml file you can add something like
Exit fullscreen mode
and will receive a nice splash screen. But my listener still is not invoked (recall that in the last quote the docs refer to window).
What’s interesting: android.R.attr has been updated for the Developer Preview, too:
Replace an icon in the center of the starting window
The duration, in milliseconds, of the window splash screen
icon animation duration when playing the splash screen
starting window. The maximum animation duration should be
limited below 1000ms.
The background color for the splash screen, if not specify
then system will calculate from windowBackground.
Place an drawable image in the bottom of the starting
window, it can be used to represent the branding of the
application.
To mee it is not clear if these additions cater for the old or new api. So, it’ll be more than interesting to see what happens in the next preview and beta versions.
Summary
So far I have not been able to make use of the new interfaces and classes regarding splash screens. The reason may be
- I am missing something 😂
- I am doing it the wrong way
- Some pieces of the puzzle are still missing
As the docs say the new api is based upon activities, we may need to configure something in the manifest. Still, I have not yet found any evidence backing this assumption.
What are your thoughts about this. Please share your impressions in the comments.
Источник