Categories
Link

“What Hacker News Says” Extension

Hacker News has been one of the places with high signal-to-noise ratio for discussions, for me. The majority of its contents is tech-related, although different topics do show up from time to time.

The “What Hacker News Says” browser extension (available for Firefox and Chrome/Chromium browsers) is a pretty cool thing that helps with a particular use case: has there been any discussion in Hacker News about this particular webpage I’m currently opening?

Pretty cool! And, yes, I found the news about it from Hacker News.

Categories
Programming

Beginner Series: Dependency Injection

Dependency Injection is a concept that did not immediately sound intuitive to my mind, especially as a non-native English speaker. I’ve read a bunch of different articles and resources about it, and found two that helped.

First, Dependency Injection Demystified. The article is quite short and I highly recommend going through it:

Dependency injection means giving an object its instance variables. Really. That’s it.

To understand what “dependency” means, here’s the famous graph about Android’s recommended app architecture:

Android's recommended app architecture

The arrows in the graph there are the dependencies. So Room depends on SQLite, the Repository depends on the Model, the ViewModel depends on the Repository, and the Activity/Fragment depends on the ViewModel.

The simplest form of dependency injection is like the primary constructor with parameter in Kotlin, like the following example:

class Person constructor(favoriteBook: Book) { /*...*/ }

Here, favoriteBook is the dependency, while the constructor parameter is the way to inject it into the Person object. This is in contrast with having the favoriteBook object created within the class.

The next question in my mind was, why do we need this?

This StackOverflow answer was the second resource that helped me with these two reasons:

Two important ones are the ability to control functionality from a central place (the Main() function) instead of spreading it throughout your program…

I think this is pretty obvious.

…and the ability to more easily test each class in isolation (because you can pass mocks or other faked objects into its constructor instead of a real value).

For testing purposes, it’s good if we can test the Person class individually and send dummy object to it (the favoriteBook object on the example above). Or, as the official manual dependency injection guide mentioned:

Dependency injection helps make these connections and enables you to swap out implementations for testing. For example, when testing a ViewModel that depends on a repository, you can pass different implementations of Repository with either fakes or mocks to test the different cases.

And the final question: if dependency injection is this simple, why are there complex tools made for it?

This is turns out relates to the first reason above:

The drawback, of course, is that you now have one mega-function that knows about all the classes used by your program. That’s what DI frameworks can help with.

Once a codebase gets really big and complex, it’s easy to imagine that manual dependency injections can go all over the place. The tools/frameworks eventually are meant to help with that.

Categories
Programming

Common Software Metaphors

A confusing abundance of metaphors has grown up around software development. David Gries says writing software is a science (1981). Donald Knuth says it’s an art (1998). Watts Humphrey says it’s a process (1989). P. J. Plauger and Kent Beck say it’s like driving a car, although they draw nearly opposite conclusions (Plauger 1993, Beck 2000). Alistair Cockburn says it’s a game (2002). Eric Raymond says it’s like a bazaar (2000). Andy Hunt and Dave Thomas say it’s like gardening. Paul Heckel says it’s like filming Snow White and the Seven Dwarfs (1994). Fred Brooks says that it’s like farming, hunting werewolves, or drowning with dinosaurs in a tar pit (1995).

Code Complete 2

One Idea That Changes Your Life

There’s a recent Ask Hacker News thread about one idea that changes someone’s life. Here are some parts that I find illuminating.

Interrogative-led questions:

Favor interrogative-led questions over leading questions.
A leading question attempts to get the listener to agree or disagree with a premise you feed to them.

An interrogative-led question often begins with the words: who; where; what; when; why.

Imagine the responses to these two questions:
– “Did you like the movie?” (Leading)
– “What did you think about the movie?” (Interrogative-led)
[…]
Asking good interrogative-led questions is essential for above-average results in many pursuits: science; engineering; interviewing; and negotiation; to name a few. It can also be an important way to de-escalate tense situations. I’ve found it especially useful when talking to subject matter experts when trying to learn something about areas I know little.

aazaa

Assume Positive Intent:

This might be super basic, but… assume positive intent.

Your parent is not your enemy. Your teacher is not your enemy. Your boss is not your enemy. The other team at work is not your enemy. The corporation is not your enemy. The other political party is not your enemy. Or, more accurately, YOU are not THEIR enemy. At best, you’re an NPC in their game. Many of them probably even want to help you, because you are another person in the world, and that feels good.

I take back what I said about this being basic. The first steps (learning your parent, teacher, boss are on your side) is pretty basic. But applying this concept to more complex systems, like corporations and communities, can be pretty advanced. But at the end of the day, what it means is that, most of the time there isn’t a conspiracy against you, there are simply incentives that you don’t understand.

darkerside

On Being Correct:

No matter how correct you are, you won’t get anywhere by making the other person feel stupid.

nstart

Putting Down Thoughts Into Words:

One thing that’s been super meaningful for me is the notion that if you don’t put something into words, either in speech or in your head or on paper, you don’t know anything about it, even if it’s a feeling or a belief or an intuition deep within you that you’ve held for as long as you can remember.

The act of simply putting a thought into words makes it immediately obvious to you if you really understand it or not, and if not, where your blind spots are.

If the thing you’re concerned with is an unresolved problem or a question, simply articulating the problem or the question can make the solution or the answer obvious. Just going through the process of putting it into words, one way or another, and being sure you’ve settled on the most concise and accurate description of it you can muster, will often make so many things that were hazy obvious, and can reveal to you areas of haziness in your own thinking that you may not have been aware of.

mwfunk
Categories
Programming

Setting Up Jetpack Navigation Component and Modal Navigation Drawer

On small screens like on mobile (setting aside how humongous smartphones tend to be nowadays), a very common pattern is to use a modal navigation drawer to allow users to navigate between one top-level destinations in the app. You’ve seen them: it’s usually the three horizontal lines on top left of an app, that can be tapped to show and hide a side drawer with a list of menu items inside of it.

Despite being a common design pattern, when I tried to learn how implement it in conjunction with the Jetpack Navigation Component, the available resources can be quite difficult to understand. They’re out there, but in my experience they’re a bit scattered and I had a hard time creating the right mental model in my mind on how to put things together.

This article is my attempt to sum things up. For things to make sense, you will need some familiarity with basic Android development and the Navigation Component itself.

Categories
Programming

General Mechanism for Scheduling Notification in Android

This article is more of a quick note about what’s involved when your Android app needs to create a notification and schedule it to appear at some time in the future. There’s a lot of articles out there that goes in details about the implementation. Think of this article as more of a summary.

Categories
Link Programming

Link: Adding Click Listener to RecyclerView using Kotlin

Recently I needed to figure out how to add click listeners to RecyclerView, in my app that’s using Kotlin as language. Kotlin supports higher-order functions, so the click listener solution can look more concise and elegant, avoiding the need to add interfaces like in Java. Andreas Jakl wrote a detailed tutorial about it here.

Categories
Programming

Kotlin: Using MediatorLiveData to Use Data from Two Tables at Once

With my current app, the main data is Subjects, where each Subject have multiple Reminders tied to it. For this purpose, I have a couple of tables in the database, which in its simplified form can be seen as below:

Subject table with:

  1. Subject ID
  2. Subject title

Reminder table with:

  1. Reminder ID
  2. Reminder timestamp
  3. Subject ID

I’m using Room for database and LiveData to pull data from the tables. The data then gets supplied to a RecyclerView, where each RecyclerView item will display a Subject with its Reminders.

RecyclerView where each row is a Subject and its four Reminder dates.

The tricky part is that, since there are two tables, I have two separate methods returning LiveData object from each table. Most tutorials out there assume the use of only one LiveData to be observed by the RecyclerView, so it can get confusing when there’s two LiveData at once.

I found a smart solution on Stack Overflow that makes use of MediatorLiveData and Kotlin’s Pair to make the whole thing work. This article is an attempt to expand on that solution by writing down my understanding of it.

This article assumes familiarity with Android concepts for RecyclerView, Room, ViewModel, and LiveData.



Create a “combination” MediatorLiveData class

The first thing to do is to create a class that extends MediatorLiveData. The interesting part is that we need to use Pair<List<Subject>, List<Reminder>> as MediatorLiveData’s type.

After that, we simply construct the class by sending it LiveData<List<Subject>> and LiveData<List<Reminder>> as constructor parameters, then put those two inside a Pair, and finally set the Pair as the MediatorLiveData object’s value.

Example of a MediatorLiveData class to handle two LiveDatas at once.

That is pretty much where the magic lies. The potentially tricky part is the addSource method and the value variable, both of which are built-in features of the MediatorLiveData.

Inside ViewModel

Inside the ViewModel, we call the repository’s methods for pulling LiveData from each table, then we return a “combination” object as we describe in the class above, and put in the LiveData as its parameters.

Methods inside ViewModel to grab two LiveData from repository and put them into one MediatorLiveData

Inside RecyclerViewAdapter

Inside the adapter, we modify its constructor to accept two Lists as parameters, the List<Subject> and the List<Reminder>.

Put in the two List<> as constructor parameters in RecyclerViewAdapter

Observe the MediatorLiveData

Finally, inside the fragment or activity that has the RecyclerView, we observe the returned MediatorLiveData from the ViewModel. When there’s any change, the observer gives a Pair containing a List<Subject> and a List<Reminder>. We can then put those two as the parameter of the adapter.

Observe the MediatorLiveData given by ViewModel, and update RecyclerViewAdapter accordingly.

Note how the Observer pattern uses a lambda with subjectsAndRemindersPair as the parameter. That is essentially the type of the MediatorLiveData in question, and by default Kotlin call that parameter it. I renamed it to subjectsAndRemindersPair to make it easier to understand.


Categories
Programming

Strategies for Creating A Single RecyclerView with Multiple ViewHolders

This article assumes familiarity with creating a RecyclerView using a single ViewHolder for each item, which is the most common use case.

Here are the possible cases where a RecyclerView might use an adapter with multiple ViewHolders instead:

A RecyclerView that uses two different layouts for each item based on odd/even position.

Case One

Have one RecyclerView to display different layouts for different items at the same time, based on certain conditions. Just as an example, here I have a RecyclerView that uses two different layouts for each item based on odd/even position.

A RecyclerView that uses identical layout for each item.

Case Two

Have one RecyclerView to display the same layout for each item. However, based on user action on certain conditions (such as during sorting or filtering action), the same RecyclerView will display the same data using a different layout. As an example, here’s a RecyclerView that uses just one layout for each item. Use your own imagination for an example where the RecyclerView at a different time uses a different layout instead.


Case 1

Here’s the general method. I’m only listing areas that differ from the usual case of RecyclerView with just one ViewHolder:

  1. We now have to create the multiple ViewHolder classes first. I prefer them to be inner classes of the custom RecyclerView.Adapter class. Pretty self-explanatory, the only possible gotcha/oddity here is that inside the class’s constructor, we create variables that directly access specific views inside a certain layout, without the class knowing about which layout it is related to.
  2. The RecyclerView adapter now must extend the more generic RecyclerView.Adapter<RecyclerView.ViewHolder>class instead of using the single custom ViewHolder class as the generic type.
  3. The RecyclerView now must override getItemViewType(), which is used to decide which ViewHolder class to be used on a certain item position in the RecyclerView.
  4. The method onCreateViewHolder() must now return the more generic RecyclerView.ViewHolder
  5. The method onBindViewHolder() must now use the more generic RecyclerView.ViewHolder object as its first parameter.

Case 2

  1. Have a variable to determine which ViewHolder should be used by the RecylerView. This will usually be inside the fragment or activity.
  2. Pass that variable as one of the parameters for constructing the RecyclerView’s adapter.
  3. Inside the adapter, create the multiple ViewHolder classes first. I prefer them to be inner classes of the custom RecyclerView.Adapter class. Pretty self-explanatory, the only possible gotcha/oddity here is that inside the class’s constructor, we create variables that directly access specific views inside a certain layout, without the class knowing about which layout it is related to.
  4. The RecyclerView adapter now must extend the more generic RecyclerView.Adapter<RecyclerView.ViewHolder>class instead of using the single custom ViewHolder class as the generic type.
  5. The RecyclerView adapter now must override getItemViewType(), and check the variable from step 2 to determine which ViewHolder to use.
  6. The method onCreateViewHolder() must now return the more generic RecyclerView.ViewHolder
  7. The method onBindViewHolder() must now use the more generic RecyclerView.ViewHolder object as its first parameter.
Categories
Programming

CSS History

Old CSS, new CSS is a great article recounting the history of CSS. With it, I can pinpoint exactly when I last regularly updated myself with its development (it was somewhere after browser prefixing hell, and before flexbox). Really useful for finding what I should catch up on, as well.