Introducing PSync

by Zac Sweers

Here on the Android team at Flipboard, we have a lot of settings for users to adjust their experience. If you throw in internal settings, we have about 100 total preferences to manage. This is a lot of boilerplate to maintain, because preferences in Android have no built-in synchronization (unlike Resources). Our

1
PreferenceFragment
class has a couple hundred lines of boilerplate fields at the top where we keep in-code mirrors to these preference values. This design is tedious, brittle, and requires a lot of overhead to keep in sync with XML. We developed a Gradle plugin called PSync to solve this problem.

PSync is an Android-specific Gradle plugin that generates Java representations of XML preferences. These Java classes can then be used directly in your code. The generated code is very much inspired by how

1
R.java
works for resources, and should feel familiar to developers. It’s easy to use, has some simple configurations for fine-tuning your generated code, and is ready to drop into both library and application projects.

A full overview can be found on the GitHub README, but here’s a quick preview:

Say you have a preference:

1
2
3
4
<CheckboxPreference
    android:key="show_images"
    android:defaultValue="true"
    />

You can reference it like this:

1
2
3
4
5
6
7
8
9
String theKey = P.showImages.key;
boolean current = P.showImages.get();
P.showImages.put(false).apply();

// If you use Rx-Preferences
P.showImages.rx().asObservable().omgDoRxStuff!

// If you need it
boolean theDefault = P.showImages.defaultValue();

The generated Java code looks like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public final class P {
    public static final class showImages {
        public static final String key = "show_images";

        public static final boolean defaultValue() {
            return true;
        }

        public static final boolean get() {
            return PREFERENCES.getBoolean(key, defaultValue());
        }

        public static final SharedPreferences.Editor put(final boolean val) {
            return PREFERENCES.edit().putBoolean(key, val);
        }

        public static final Preference<Boolean> rx() {
            return RX_SHARED_PREFERENCES.getBoolean(key);
        }
    }
}

It’s robust, fully tested, and should be ready for use with standard XML preferences. The process of writing tests for a plugin like PSync is worth its own blog post or talk, so look forward to that coming up. Future plans for this project include adding support for mixing in your own non-XML preferences, and supporting the full range of the SharedPreferences API.

We hope you find it useful, and welcome contributions and feedback on the repo: https://github.com/Flipboard/psync

If you like open source and working on cool projects, we are looking for talented Android engineers to join our team here in Palo Alto, California! Apply here

Add to Flipboard Magazine.