Posts

Supporting RTL languages on Android, Bidi (Bidirectional) text

Recently I've found myself spending a lot of time trying to make sure things look nice on both LTR as well as RTL locales, so that folks with UIs in Arabic, Hebrew, Persian, or Urdu can also have an A+ experience on Android. I ran into an annoying problem where international phone numbers, such as +9708675309 would show up in the app as 9708675309+. The issue was that in RTL languages, numbers should be LTR, so the phone number portion was displayed correctly, but unfortunately the + was displayed on the right side of the phone number. After a good amount of Googling, the fix is actually really simple. Just place the Left-to-Right Isolate Unicode mark on the left of the text you want to be LTR, and then place the Pop Directional Isolate Unicode mark on the right of the text, so that it doesn't make the entire rest of the text LTR. It looked sort of like this in Kotlin: "\u2066+9708675309\u2069" and it worked like a charm!

A list of useful RxJava things!

Over the past year I've learned a bunch of useful tricks for RxJava, and I'm gonna post them here as I remember them or use them. Hopefully this'll grow to a large list/cheatsheet! Here is a way to take the first element multiple flowables that may emit the same data (but loaded from disk or memory or network) and then emit the first one that returns. Concat checks flowable1 first, and then flowable2. I got this from this blog post from Dan Lew . Flowable .concat(flowable1, flowable2) .firstElement() Dan uses it for loading data first from memory, then from disk, and finally from network, so there's a lot of other stuff you can add to it too. He demonstrates how you can use a side effect to create a flowable that saves to network requests to disk and memory whenever you load it from remote: val cache: Flowable<Data> = ... val network: Flowable<Data> = ... val networkWithCaching: Flowable<Data> = network .doOnNext { data -> add...

Reliably showing the Android keyboard for ViewGroups too

The other day, I was browsing through the Android blog world (make sure to check out https://blog.danlew.net/ ), and found this really awesome blog post from the developers over at Square about reliably displaying the Android keyboard, which is controlled by a rather difficult API. After trying out their code, however, I realized that it did not work for my purpose which was to focus a SearchView after clicking a button. The bug was really strange, because while we had called requestFocus() on the SearchView , when we queried it for isFocused , it would return false ! Turns out, after a lot of struggling, I found that requestFocus() actually may give focus to one of the descendants of the View instead. SearchView is actually a ViewGroup , so focus was actually given to a TextView that was a child of the SearchView . After learning about this, the fix was easy: Instead of only directly checking the SearchView for isFocused , do a recursive check on the focusedChild of the Searc...

Thoughts about what makes a great developer

People seem to agree that a great developer is better than many mediocre developers and I think that is true with good reason. Developers are craftsmen, in my opinion, like stonemasons, woodworkers, or carpenters. We make things that are useful to people outside the field, and, if well made, can be even artistic to those who understand the field. Similarly, like craftsmen, you can't replace someone with a skilled hand with many people with unskilled hands. They tried using automation and large factories to churn out things like mass-produced furniture, but at the end of the day, the IKEA fast furniture just really isn't up to the quality of a similar piece made by a real artisan. However, developers these days seem to earn a lot more than other craftsmen, and I think that is largely because for many people buying things like furniture or pottery (especially the young folks like me), cost is a lot more important than quality and most people would rather pay, say, 10% of the cost...

Is it worth it to speed up caches even more?

I think about a cache like a faster database that you check before checking the main database, but at the end of the day, if you do have a cache, you have to check 2 databases. If the cache is sitting in some remote machine, like Memcached, you run into various things that may slow it down by hundreds of microseconds such as intrinsic latency or network latency, and if you choose to query between datacenters you may even get dozens of milliseconds of latency. I wonder how important it would be to shave off these microseconds, or to even just find a way that we could avoid cache queries when they are misses. I'll keep thinking on this and read more about how hyperscalers use caches.

Recyclerview History

Recently I discovered this old talk from Google I/O 2009  and in the first 14 minutes they explain the Recyclerview, the Adapter, and the Viewholder incredibly well. Here's a few important takeaways from this video, although I'd recommend watching it in its entirety: 1. The Adapter takes in data and generates Views via a function Adapter.getView() that takes in a position, a View, a parent ViewGroup, and returns a View. 2. The naive solution to implement Adapter.getView() would be to use the position to get the right data and then just inflate a new View that belongs to the parent ViewGroup. 3. The first optimization is that we can avoid inflating new views by just recycling old views when they leave the visible area. We would use the position, the View (recycled when it is not visible) and just bind new data into that existing View. 4. The second optimization is that we can avoid doing new findViewById() calls by storing all the referenced Views in a class called a ViewHold...

Can the Mirai botnet teach us how to make Android apps faster?

Recently, I've been spending a lot of time thinking about Android app performance, specifically regarding network requests. Developers working on mobile apps are allowed a lot more customization for low-level details (for example, we get to customize our own network stack!) but in exchange, we must plan for our applications to work in some crazy environments. Our users might be on WiFi, 5G, 4G, or even GPRS. They could be sitting in a coffee shop or riding on a high speed rail with their cell service hopping to a new cell tower every 10 minutes. They could even be using satellite if they're sailing on a boat or flying through the air. On top of all this, we need to be able to support everyone using a $100 to $1000 smart phone. Interestingly enough, the conditions that mobile developers have to run their mobile apps in is actually reminiscent of the conditions that botnet developers have to run their malware in! The Mirai botnet malware ran with a tiny memory footprint, a tiny e...