Description
On Android ViewModel is more - provides easy state management across view lifecycle events. When an Activity or Fragment gets recreated, subscribing to observe LiveData gives us the latest value, thus orientation changes are easy to manage. But sometimes this is not desirable. For instance, we would not want another screen to open again or another message to show again when we rotate the device, since the value is preserved in LiveData.
`BriefAction` type represents these actions and, in combination with the rest of the pattern, enables consuming of such actions only once.
The beauty of this pattern is in its easy use and the way it nicely and intuitively reads for initiating display or navigation action from a ViewModel simply by calling:.
`display(ShowMessage(R.string.hello))` or
`navigateTo(SettingsScreen)`
or from Activity / Fragment
`viewModel.display(ShowMessage(R.string.hello))` or
`viewModel.navigateTo(SettingsScreen)`
AndroidBriefActions alternatives and similar packages
Based on the "Navigation" category.
Alternatively, view AndroidBriefActions alternatives based on common mentions on social networks and blogs.
-
SlidingTutorial
Android Library for making animated tutorials inside your app -
Compose Destinations
Annotation processing library for type-safe Jetpack Compose navigation with no boilerplate. -
Bubble Navigation
๐ [Android Library] A light-weight library to easily make beautiful Navigation Bar with ton of ๐จ customization option. -
FragNav
An Android library for managing multiple stacks of fragments -
RecyclerTabLayout
An efficient TabLayout library implemented with RecyclerView. -
AnimatedBottomBar
A customizable and easy to use BottomBar navigation view with sleek animations, with support for ViewPager, ViewPager2, NavController, and badges. -
Duo Navigation Drawer
A flexible, easy to use, unique drawer library for your Android project. -
Chip Navigation Bar
An android navigation bar widget -
BubbleTabBar
BubbleTabBar is a bottom navigation bar with customizable bubble-like tabs -
Compose Navigation Reimagined
๐ Type-safe navigation library for Jetpack Compose -
Alligator
Alligator is a modern Android navigation library that will help to organize your navigation code in clean and testable way. -
Fragula 2
๐ง Fragula is a swipe-to-dismiss extension for navigation component library for Android -
PagerSlidingTabStrip
An interactive indicator to navigate between the different pages of a ViewPager -
Okuki
Okuki is a simple, hierarchical navigation bus and back stack for Android, with optional Rx bindings, and Toothpick DI integration. -
CarMarker-Animation
Marker Animation android googlemap -
Dual-color-Polyline-Animation
This library will help to show the polyline in dual color similar as Uber. -
Keyboard Dismisser
Dismiss your keyboard by tapping anywhere outside it. -
TypedNavigation
A lightweight library to help you navigate in compose with well typed functions. -
Facilis
A sleek, out of the box, easy to understand and use, swipe gesture based Navigational Library for android. -
fragstack
Memory efficient android library for managing individual fragment backstack. -
what3words Autosuggest EditText
An Android library to use what3words autosuggest -
EasySideNavigation
Create side navigation in easy way
Appwrite - The open-source backend cloud platform
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of AndroidBriefActions or a related project?
README
implementation "com.vladmarkovic.briefactions:briefactions:$briefActionsVersion"
Benefits
Why use brief-actions library pattern:
- Prevent short-term actions reoccurring (i.e. on screen rotation)
- Easy, readable and intuitive way to call display and navigation actions
- Code traceability
- Default
observe
function allows only one observer to subscribe.
On Android, in combination with LiveData, ViewModel is more than what it might be on some other platforms. It also represents an architectural component for easy state management across view lifecycle events. When an Activity or Fragment gets recreated, subscribing to observe LiveData gives us the latest value, thus orientation changes are easy to manage. But sometimes this is not desirable. Some state delivered by certain action might be only relevant at the time when the action happened. For instance, navigating to another screen, or displaying a non-persistent message. In these cases we would not want another screen to open again or another message to show again when we rotate the device (value is preserved in LiveData).
BriefAction type represents these actions and in combination with LiveAction, helper observers, ViewModel and the rest of the pattern, enables consuming of such actions only once.
The beauty of this pattern is in its easy use and the way it nicely and intuitively reads for initiating display or navigation actions from a ViewModel simply by calling:.
display(ShowMessage(R.string.hello))
ornavigateTo(SettingsScreen)
or from Activity / Fragment
viewModel.display(ShowMessage(R.string.hello))
orviewModel.navigateTo(SettingsScreen)
Another benefit is improving code traceability, which is often a disadvantage of MVVM comparing to MVP.
Using command+tap on the defined action, we can trace where it is used or handled.
Also, by default observe
function allows only one observer to subscribe for observing
display or navigation actions. This ensures prevention of opening the same screen or showing of same message
multiple times. If you want you can override this behaviour by passing true
as the last function param.
Use
- Extend the library ViewModel when you create your view model.
- Create your BriefActions (inside VM for scoping or outside).
- Call them with
display
ornavigateTo
functions defined in the ViewModel.
You can call them directly from the view model, or from Activity / Fragment. - Observe them inside Activity / Fragment.
Important Note:
DisplayAction and NavigationAction are sent using LiveAction which by default allows for only one observer to subscribe with the defaultobserve
function. If you want to enable multiple observers, you will need to explicitly passtrue
for the lastadd
param.
So:viewModel.displayActions.observe(lifecycleOwner: LifecycleOwner, observer: Observer<in A>)
is equivalent tosetObserver
viewModel.displayActions.observe(lifecycleOwner: LifecycleOwner, observer: Observer<in A>, add = true)
is equivalent toaddObserver
(same forviewModel.navigationActions
)
Just be aware that:- if you
add
several observers and thenset
one after them, it will remove all the previously added ones. - if you
set
an observer and thenadd
one after, there will be two subscribed.
Example
class MyViewModel(private val auth: SomeAuth) : ViewModel() {
//...
fun login(userId: String, password: String) {
if (userId.isNotBlank() && password.isNotBlank()) {
signIn(userId, password)
} else {
display(ShowMessage("Please fill out all the fields."))
}
}
private fun signIn(userId: String, password: String) {
// helper extension function for launching a coroutine
launchHandleOnMain {
suspended = {
success = auth.signIn(userId, password)
if (success) navigateTo(DashboardScreen(userId))
else navigateTo(SignUpScreen)
},
onError = { error ->
display(error.message)
}
}
}
sealed class MyNavigationAction : NavigationAction {
object SignUpScreen : MyNavigationAction()
data class DashboardScreen(val userId: String) : MyNavigationAction()
}
}
data class ShowMessage(val message: String) : DisplayAction()
class MyActivity : AppCompatActivity() {
private val viewModel by viewModel<MyViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//...
viewModel.display(ShowMessage("Hello!"))
viewModel.observe(this, DisplayActionObserver { displayAction ->
when (val data = displayAction) {
is ShowMessage -> Toast.makeText(this, data.message, Toast.LENGTH_SHORT).show()
}
})
viewModel.observe(this, NavigationActionObserver { navigationAction ->
when (navigationAction) {
is MyNavigationAction -> handleMyNavigationAction(navigationAction)
}
})
}
private fun handleMyNavigationAction(navigateTo: MyNavigationAction) =
when (val data = navigateTo) {
is SignUpScreen -> startActivity(SignUpActivity.newIntent())
is DashboardScreen -> startActivity(DashboardActivity.newIntent(data.userId))
}
}
License
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*Note that all licence references and agreements mentioned in the AndroidBriefActions README section above
are relevant to that project's source code only.