Coder Social home page Coder Social logo

psync's Introduction

Development in this repository is stopped. Future development continues on https://github.com/hzsweers/psync

==========================

PSync

PSync is a gradle plugin for android projects to generate Java representations of xml preferences.

Some applications have a lot of preferences, each their own keys, default values, and more. These tend to be stored in xml files (under res/xml), and don't have any programmatic linking of their values. The result? You have to manually keep these values in sync with your Java code. Yikes!

We got tired of dealing with this at Flipboard. Our preference class ended up with 200+ lines of boilerplate at the top that we manually had to keep in sync, and it was becoming a nuisance. PSync was developed to resolve this, and we hope it helps you too!

Setup

Apply the PSync plugin to your module below your android plugin application

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.flipboard:psync:1.1.5"
  }
}

apply plugin: 'com.android.application' // Can be library too
apply plugin: 'com.flipboard.psync'

The PSync plugin will create a generating task for each of your variants, and will generate a file at compilation that will be included in your classpath. This process is purposefully very similar to how the R.java file works. The default name for this class is P.java, but you can configure it to be another name if you wish.

Speaking of configuration, here's how you can configure PSync to work for you.

psync {
    className = "MyClassName"
    includesPattern = "**/xml/<mypatternforfiles>.xml"
    packageName = "com.example.myapp"
    generateRx = true
}

Let's take a look at each:

className is the name of the class. The default is just P.

includesPattern is an ant-style includes pattern for preference xml files in your resources. This is useful if you have a lot of other xml files and want to save the plugin a little work by filtering out non-pref ones. In Flipboard, all our preference files are prefixed with prefs_, so our includes pattern would be **/xml/prefs_*.xml. The default is to parse all xml files in xml resource directories.

packageName is what you want to use for the package name of the generated resource classes. The default behavior of the plugin is to retrieve this from your variant's applicationId value. NOTE: Library projects MUST specify this, since they don't have applicationId values.

generateRx is a flag indicating whether or not you want code generated for usage with Rx-Preferences, which is a great library that adds reactive bindings around SharedPreferences

Usage

Using the generated file is easy, and should feel very familiar to how you would use R.java.

Each preference is represented by a static inner class, with a key field, a defaultResId field if it's a resource, and some or all of following functions:

  • defaultValue() for retrieving the default value
  • get() for retrieving the current stored value
  • put() for storing a new value
    • NOTE: This returns an Editor instance, where you much apply or commit the change(s)
  • rx() for retrieving an appropriate Rx-Preferences instance of Preference, if you enabled generateRx above.

These functions are generated when appropriate. If no default value or resource reference is specified, the plugin will not try to guess the type and generate code for it.

First thing's first: Initialize your P.java file in your Application's onCreate() method.

public class MyApp extends Application {

    @Override
    public void onCreate() {

        // Required
        P.init(this);

        // Optional
        // By default, it will initialize its internal SharedPreferences instance to the system default
        // You can change its used instance at any time
        P.setSharedPreferences(myOtherInstance);
    }

}

Let's take a look at an example. The following xml preference:

<CheckboxPreference
    android:key="show_images"
    android:defaultValue="true"
    />

Becomes this Java code:

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);
        }
    }
}

You can now reference this in code like so:

String theKey = P.showImages.key;
boolean theDefault = P.showImages.defaultValue();
boolean current = P.showImages.get();
P.showImages.put(false).apply();

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

Nice and simple right? Note that the entry block's name will be a camelCaseLower conversion of the key.

Let's look at a resource example now. The following preference:

<Preference
    android:key="server_url"
    android:defaultValue="@string/server_url"
    />

Becomes the following Java code:

public final class P {
    public static final class serverUrl {
        public static final String key = "server_url";
        public static final int defaultResId = R.string.server_url;

        public static final String defaultValue() {
            return RESOURCES.getString(defaultResId);
        }

        public static final String get() {
            return PREFERENCES.getString(key, defaultValue());
        }

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

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

Notice that resources are handled a little differently. This is intentional, and for convenience. Using this code now looks like this:

String theKey = P.serverUrl.key;
int theResId = P.serverUrl.defaultResId;
String theDefault = P.serverUrl.defaultValue();
String currentValue = P.serverUrl.get();
P.serverUrl.put("https://example.com").apply();

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

Easy peasy. Enjoy!

Contributing

We welcome pull requests for bug fixes, new features, and improvements to PSync. Contributors to PSync repository must accept Flipboard's Apache-style Individual Contributor License Agreement (CLA) before any changes can be merged.

psync's People

Contributors

zacsweers avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.