Skip to content

mykola-dev/bindingtools

Repository files navigation

bindingtools

JitPack

Lightweight helper library for Android Kotlin development

  • Shared Preferences delegates
  • Bundle args delegates
  • Resources delegates
  • View<->Data Binding

Quick Setup

Step 1. Add the JitPack repository to your build file

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

dependencies {
    compile 'com.github.deviant-studio:bindingtools:{latest_version}'
}

Documentation

Data Binding

Let's say you have an Activity:

class MainActivity : AppCompatActivity() {

    private lateinit var textLabel: TextView
    private val viewModel = MainViewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        textLabel = findViewById(R.id.text)
        bindViews()
    }

    private fun bindViews() {
        // ...
    }
}

and a ViewModel:

class MainViewModel {
    var text: String = ""

    fun sayHello() {
        text = "Hello, World!"
    }
}

It would be nice if we can bind text field to the view. Let's modify ViewModel:

class MainViewModel : Bindable {
    var text: String by binding("")

    fun sayHello() {
        text = "Hello, World!"
    }
}

and Activity:

private fun bindViews() = withBindable(viewModel) {
    bind(::text, textLabel::setText, textLabel::getText)
}

Thats it! Now we can set TextView's text like:

viewModel.sayHello()

Also library allows you to simplify TextView/EditText bindings to this:

withBindable(viewModel) {
    bind(::text, textLabel)
}

Comparison with Google Databinding library

+ don't have to write BindingAdapters
+ no code generation (no more missed BR.id, don't have to force clean in any unclear situation)
+ great code completion (compared to XML)
+ clean XML files
+ can bind anything to anything, not only the View
+ can be used with Anko (and any programmatically created views)
+ much cleaner way to implement 2-way bindings

- some reflection
- not from Google
- only for Kotlin apps
- no observables (yet?)

Shared Preferences binding

It's so annoying to deal with SharedPreferences directly:

final String ageKey = "age";
final String userNameKey = "userName";
final String adminKey = "admin";
SharedPreferences prefs = getSharedPreferences("main_prefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(ageKey, 12);
editor.putString(userNameKey, "Luke");
editor.putBoolean(adminKey,true);
editor.apply();

Fortunately now we have Kotlin and the bindingtools! First, declare the PreferencesAware class

class Prefs(ctx: Context) : PreferencesAware {

    override val forcePersistDefaults = true
    override val sharedPreferences: SharedPreferences = ctx.getSharedPreferences("main_prefs", Context.MODE_PRIVATE)

    var age by pref(0)
    var userName by pref("")
    var isAdmin by pref(false)

}

Now you can use preferences like this:

val prefs = Prefs(this)
prefs.age = 12
prefs.userName = "Ani Lorak"
prefs.isAdmin = true

println("the name is ${prefs.userName}")

Bundle arguments binding

Dealing with args bundle has never been such simple before. Let's declare another one activity:

class SecondActivity : AppCompatActivity() {

    val userName: String by arg("")
    val age: String by arg("")
    val country: String? by arg()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        println("$userName $age $country")  // that's it. just read the properties
    }
}

Start activity with convenient bundle builder:

startActivity<SecondActivity> {
    SecondActivity::userName to "Ivo Bobul"
    SecondActivity::age to 99
    SecondActivity::code to 65536
}

or build the bundle separately:

val args = bundle {
    SecondActivity::userName to "Slavko Vakarchuk"
    SecondActivity::code to 100500
}

Resources binding

Same rules can be used when using resources:

private val appName: String by res(R.string.app_name)
...
println(appName)

Projects using this lib