Tumblr Engineering (Posts tagged Android)

1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

Introducing Graywater for Android

Introducing Graywater, Tumblr’s framework for decomposing complex items in a RecyclerView list in order to improve scroll performance, reduce memory usage, and lay a foundation for a more composition-oriented approach to building lists. With Graywater, the app now scrolls faster and crashes less often, and it also gives us a solid foundation for building new features faster and better than before.

On screens that display posts, such as the dashboard, the Tumblr Android app customizes one adapter across multiple screens. This approach results in a complex adapter, and over time, our previous solution became difficult to manage and hard to reason about since there was no consistent place for screen-specific behavior.

Furthermore, each post type had its own layout and viewholder, which meant that once a user encountered a post type they hadn’t seen on that screen before, the entire post had to go through the inflate, layout, and draw process. Once offscreen, the post would take up large chunk of memory in the RecyclerView pool.

image

Graywater solves this by rendering only the parts of a post that are visible and reusing the parts of a post that appear in other posts, such as the header and footer. By breaking up a large post into smaller components, the UI thread has to do less on each scroll. Even though there are more view types, each individual view type is smaller, so memory usage is lower.

For example, a photoset post may be composed of ten photos, one after another. In the previous architecture, a photoset layout with headers and footers would be inflated and the photo views added in afterwards. If the viewholder is recycled and the next photoset post only has one photo, the extra photo views are discarded. With Graywater, each individual photo view is recycled separately, which allows RecyclerView to reuse the photo views that appeared earlier in the photoset.

This idea is based off of Facebook’s post on a faster news feed and Components for Android, which have been open-sourced as Litho.

Graywater differs from other RecyclerView libraries by being small (a single file!) and flexible enough to work within your model architecture. For libraries like Epoxy and Groupie to accomplish sub-item recycling, complex items like posts need to be decomposed into smaller viewmodels beforehand. For Litho to flatten view hierarchies and perform fine-grained recycling, existing XML layouts need to be converted to layout specs.

By converting to Graywater, we’ve been able to reduce OutOfMemory errors by 90% and dramatically improve scroll performance. It is now much easier to add new item types that are composed of preexisting post components. We have also migrated screen-specific logic to the screen itself by injecting the customized component into the adapter. By open-sourcing Graywater, we’re hoping the Android community will achieve similar performance and architecture gains, and we’re excited to hear what the community builds next!

- @dreamynomad

android engineering graywater
Alpha or Beta? The Choice is Yours, Android Users.Earlier this year, we asked our Android users to join an exciting new open beta program to help us squash bugs. We’ve since developed something stronger. Something that opens your mind in ways you’ve...

Alpha or Beta? The Choice is Yours, Android Users.

Earlier this year, we asked our Android users to join an exciting new open beta program to help us squash bugs. We’ve since developed something stronger. Something that opens your mind in ways you’ve never thought possible. A way to opt into the mystery, the wonder, the beauty that is the latest Tumblr app: alpha.

What’s different? While the open beta app is updated twice a month, the closed alpha app updates with the latest build every night. It will also set your mind free. Both are great things to help you find bugs, which help us make Tumblr even better.

Who can join? A very limited number of Android users will be accepted for membership on a first-come, first-serve basis. Testers should use Tumblr daily and be diligent in alerting us when they find a bug. That’s what this whole thing is for, after all.

How does that work? When you see a bug, shake your phone with gleeful rage. Rage-shaking opens an email. Describe the bug and hit send.

What else? Well, heck. That’s what the FAQ is for.

Now that we have that settled, go on and apply for membership.

android
kevinthecity

Ordered Broadcasts in Android

engineering

Simulating background / foreground notifications in Android

In a recent article I wrote for objc.io detailing how notifications in Android differ from those in iOS, a reader messaged me and asked

“How do I detect if an Application is in the foreground when a notification arrives? Android seems to be missing this functionality, where iOS has it readily available.” paraphrased

It’s true, there is no intrinsic differentiation for foreground and background notifications in Android. This is largely a fundamental difference in how Android handles notifications altogether. In Android, the developer has full control over the lifecycle and presentation of a notification, and such, it could be presented at any time. Whether the app is actively running or not, the developer is responsible for presenting notifications to the user. The same callbacks are presented in all scenarios. In light of this question, I created a sample project to demonstrate one such approach to this problem.

OrderedBroadcast Example (Github)

See the demo video (YouTube)

Ordered Broadcast Strategy

One strategy for mitigating this problem is using a not-so-well-known API titled sendOrderedBroadcast (used in place of sendBroadcast) available on any Context within your application. An ordered broadcast takes the same intent you would use with a normal broadcast, the primary difference lies within the receiver. By setting a priority on the IntentFilter using setPriority(int priority) you tell the system that this receiver should be called before any other. Lets take a look at some code.

@Override
protected void onResume() {
 super.onResume();
 IntentFilter filter = new IntentFilter(AlarmReceiver.ACTION_RECEIVE_NOTIFICATION);
 // The default priority is 0. Positive values will be before
 // the default, lower values will be after it.
 filter.setPriority(1);

 // It’s good practice to register your BroadcastReceiver’s in
 // onResume() unless you have a good reason not to
 registerReceiver(mForegroundReceiver, filter);
}

When registering a receiver programmatically, we have the ability to set a priority on it. You might have seen this before, but never known why to use it. Well, now you know! Ordered broadcasts will inspect this priority before sending to the receivers. Receivers with a higher priority will catch the broadcast first, and then send itself on to lower ones (default is 0).

The beauty of using an ordered broadcast is that you (the developer) can decide whether or not your want that broadcast propagated. For example, if you have two BroadcastReceivers catching q broadcast, one as a foreground receiver and one as a background receiver, you can tell the foreground receiver to abort the broadcast using abortBroadcast(), so that any lower priority receivers won’t catch it.

private BroadcastReceiver mForegroundReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
 // Don’t send this intent to anyone else!
 abortBroadcast();

 // Let the user know we received a broadcast (if we want).
 Toast.makeText(MainActivity.this, R.string.received_in_foreground, Toast.LENGTH_SHORT).show();
 }
};


Summary

That’s it! Using the ordered broadcast strategy, you can send the same intents for background and foreground notifications, and display them in different ways by utilizing different priorities.

You can go even crazier with this approach by setting different priorities for different Activitys. Maybe when you’re on the main screen, you want to intercept all notifications, but on subscreens you only want to intercept notifications related to that specific screen. The possibilities are endless!

software development Android Development android
haseman

The Android App Gauntlet

haseman

adb shell monkey —throttle 100 -v -p com.your.packagename 50000

I like to put my app through ‘the Gauntlet’ every night.  50,000 random events.  Make sure you plug your headphones in first (so you don’t annoy your co-workers when the monkey turns the music on.)  I like to leave the throttle at 100 to keep the events coming in at a ‘crazed’ rate rather than having them come in at an unthrotteld ‘cocaine-bender’ speed.

I run this at least once a day on my current dev build.

android android development dev programming