Finally connecting everything together šŸ˜Š

Daniel Rendox - Sep 20 '23 - - Dev Community

On the 2nd of August, I promised to document my progress during these two months. Hereā€™s a report of my past two weeks of learning and building in public.

In the last time, honestly, I didnā€™t have much desire to be active in this digital world of developers. Thatā€™s because my higher education has started, and there are so many new connections out there that itā€™s actually too much for me. šŸ˜†

However, I need to summarise what Iā€™ve done to feel the progress towards the end goal and be motivated, purposive, and consistent. While I'm delighted to return to my comfort zone and savor this exceptional phase of my life, it's important that I remain engaged in all its facets.

About two weeks ago, I was struggling with balancing learning and building. Thatā€™s because I wanted to build my program, and at the same time I didnā€™t know enough to actually start without messy code. Although I started in some aspects ā€” UI, business logic, and data storage, I couldnā€™t connect everything together.

However, a few days ago, I was so happy to discover that I actually know everything I need to build my program! Of course, my knowledge isnā€™t deep, but itā€™s enough to create a base of a scalable program without messy code and following all the recommended best practices.

I donā€™t know whether itā€™s because I developed that mindset for learning only the necessary concepts and leaving the rest for the time I actually need a certain thing or itā€™s because I already knew much and just underestimated my progress, but in the first week of this period I learned all the remaining concepts I needed and discovered such pleasing truth. Seriously, look at the plan Iā€™ve been following:

  1. Android basics
  2. Kotlin
  3. Jetpack Compose basics
  4. Advanced state, side effects, and Gradle
  5. Inline functions, testing, introduction to Coroutines and Flow ā—€ļø
  6. Databases and modularization
  7. Interaction with remote API
  8. Dependency injection
  9. Architecture (MVVM, MVI) and other stuff šŸ†

ā—€ļø ā€” where I was two weeks ago

šŸ† ā€” where I am now

Now the plan is to catch up on building my program, fill in the gaps in knowledge while working, and actually complete the challenge in the remaining time. (at least Iā€™ll try).

Oh, and here's what I've learned:

Interaction with remote API

Nothing interesting in remote API itself actually. The basics are not difficult at all and I donā€™t need it for now. Contrary to what I expected, it didnā€™t help me better understand coroutines either.

However, it was a good introduction to Rest API. It also helped me a lot in understanding dependency injection.

Here is the course Iā€™m speaking about.

Dependency injection (di)

I learned the basics of Hilt with the help of this amazing codelab. This helped me understand how di and di frameworks work overall. And itā€™s not about learning Hilt because I actually donā€™t plan to use it in my app.

I don't really understand why people perceive dependency injection as a complex thing. For now, I see it just as a workaround in situations when I can't pass dependencies in constructors (a typical situation in Android). According to what I've seen in the codelab, manual di requires almost the same amount of code. So it currently looks simpler and safer to me.

I would appreciate it if someone explained to me what all the fuss is about.

Anyway, I probably just don't know something because experienced guys say di is very important. I was right about the manual di, though. It is indeed a great option because it eliminates the overhead created by di frameworks. But this is not an option for me because frameworks provide some template while doing it manually gives me so much freedom that I risk of creating a monster, riddled with bugs.

So I learned hilt and found out that I couldn't use it in my project right after that. šŸ˜ I can't use it because I aim to expand my project to iOS using Kotlin Multiplatform, but Hilt is a pure Android thing. So I'll use the second most popular di framework ā€” Koin.

Databases

When I first met the concept of databases, I found out that database programming is very limited compared to object-oriented programming. Lately, when I got back to this topic again, I found out that itā€™s not difficult at all, and you donā€™t need to read a book or pass a crash course to correctly design database schemes.

The first tricky thing is database inheritance. There are three approaches here ā€” look at this answer on Stack Overflow. Due to limitations of the framework and other considerations, I picked the first one.

The second tricky thing is modeling relationships such as one-to-many and many-to-many. This is perfectly explained here.

When it comes to choosing the framework, Room is the obvious choice for Android. But this is once again a pure Android thing that doesnā€™t work with KMM, so I use SQLDelight instead.

Modularization

Checked the information about the recommended architecture of a project that consists of data, domain, and presentation layers. Also found out about CLEAN architecture from this example.

I didnā€™t dive into modularization itself though. Thatā€™s because Iā€™ll introduce it later when my project grows.

There need to be 3 main modules: app, feature, and core. For now, I decided to use packages instead of modules and have several sub-packages for data, domain, and presentation.

MVVM vs MVI

Finally, when it comes to a serious Android project, there are lots of considerations. One of them is whether to use mvvm or mvi. Other solutions are generally not an option because they are too legacy. I decided to use MVI because of its benefits. There are many drawbacks too, but we can work around them. One of the decisive factors is that itā€™s more modern and Google recommends MVI for Jetpack Compose projects now. šŸ˜Ž

With XML, the situation is different because, AFAIK MVI isnā€™t good for performance there. It causes the whole UI to rerender each time something changes, which is not true about compose since its compiler is smart enough.

Thanks, Philipp for the great explanation.


There is another interesting thing, by the way. Although itā€™s better for beginners to follow the recommended practices and decide on something only when they get some experience, one can essentially do everything they want and use their own solutions as long as everything works correctly, the code is readable and still follows the best practices.

For example, the matter of whether to use ViewModel is questionable. I recently discovered that the main reason we use it is because it caches the data so that we donā€™t need to execute network requests when nothing changes. We also save resources by not fetching data when a configuration change occurs. There are other benefits of ViewModel. Here is a great talk related to this topic.

However, there are alternative approaches to achieving that. For example, compose provides rememberSaveable for saving state across configuration changes and even across activity recreations.

You Don't Need Android ViewModel, Here is Why

Explanation of why you don't need ViewModel component in your Android application and a list of alternative solutions that I use.

favicon techyourchance.com

So there are lots of ways for achieving the same thing and itā€™s not necessary to use only recommended solutions. Getting more experience, Iā€™m becoming more and more convinced in that.

Ending

I wrote this article for myself mainly. But if you read this far, thanks for being interested in me. šŸ¤—

If you're learning Android and struggling with some of these topics, you can DM me onĀ TwitterĀ or email me (daniel.rendox@gmail.com) and we'll figure it out together.

. . . . . . . . . . . . . . . . . . . .