Simple Android — 2
Abusive usage of Frameworks and Libraries
In the past, we, as android developers, didn’t have so many options to achieve something that fulfills our requirements or they were not our first options because who wants to use some old fashioned frameworks or concepts, right?
That being said, we now have many frameworks or libraries or even good programming languages that are really powerful.
This considerable amount of tools, increases the complexity with the wrong usage like “Hey, this tool is awesome, I can use that here, here and here also here”. Soon you are realizing that your codebase is getting more confusing day by day. If you are familiar to android techs, I know what you are thinking now, StateFlow, SharedFlow, RxJava, Coroutines, LiveData, Arrow, and their tens of extension libraries and so on.
For today, I want to focus on abusive usage of Kotlin collections, Flow and wrong usage of SQLite then how it increases the complexity.
Sample 1 — Accessing the User and UserPosts
@Query("SELECT * FROM user")
fun getAll(): Flow<List<User>>
@Query("SELECT * FROM userposts")
fun getAll(): Flow<List<UserPosts>>
coroutineScope.launch {
users.combine(posts) { users, posts ->
val currentUser = users.firstOrNull { user -> user.uid == loggedUserId }
currentUser?.let {
val userPosts = posts.filter { post -> post.userId == currentUser.uid}
UserAndPosts(currentUser.uid, currentUser.firstName, currentUser.lastName, userPosts)
}
}.collect { userWithPosts ->
userWithPosts?.let { notifyScreen(it) }
}
}
This one is just a simple usecase, now imagine you have hundreds usecases, local data sources and viewModels do the similar filterings, mappings, and one day there will be new filtering requirement asked from business.
At this point, you are not sure that where you can add new filterings without breaking other functionalities, and you will think that this is too risky and duplicating the usecase is a good solution for bug free solution, and soon you will be having usecases 99% same logic and you increased complexity and you caused a mess.
How to avoid this?
Simple! just use your tools correctly!
First, create another Dao or function that has correct usage of SQLite
@Query(
"SELECT * FROM user" +
" JOIN userposts ON userposts.userId = user.uid WHERE user.uid =:uid"
)
fun loadUserAndPosts(uid: Int): Flow<Map<User, List<UserPosts>>>
Then use it like a boss!
coroutineScope.launch {
userAndPosts.collect { userAndPost ->
notifyScreen(userAndPost)
}
}
From the example, you might think that this is not a big issue but in a big project remember that you will have hundreds objects for those type of work and adding new properties to existing classes is mess!
Last words of today, “Abusive usage of Frameworks and Libraries” is a serious topic. I think we all suffer from this, feel free to contribute to this post with other tools!
https://developer.android.com/kotlin/flow
https://developer.android.com/training/data-storage/room
https://developer.android.com/training/data-storage/room/relationships