Coder Social home page Coder Social logo

albodelu / android-extras-delegates Goto Github PK

View Code? Open in Web Editor NEW

This project forked from takhion/android-extras-delegates

0.0 1.0 0.0 85 KB

Kotlin property delegates to manage Android Intent and Bundle extras

License: MIT License

Kotlin 100.00%

android-extras-delegates's Introduction

Android Extras Delegates

Contains a collection of Kotlin property delegates to manage Android Intent and Bundle extras.

See this article for more information.

Usage

Create an object (anywhere, although by convention it's inside an Activity) and declare inside it some delegated extension properties over Intent or Bundle (all types are supported):

package com.example

class SomeActivity : Activity() {

    object IntentOptions {
        var Intent.someExtra by IntentExtra.String()
    }
}

IntentExtra and BundleExtra are two empty object which serve as containers for all delegates.

If not specified, the name of the extra will be the fully qualified name of the containing class, followed by the property name (in the example: "com.example.SomeActivity.IntentOptions::someExtra"). It is also possible to specify a custom prefix instead of the fully qualified name of the class, which is useful when creating nested delegates (see below).

If a default value is not specified, the returning type will be nullable.

To use a delegate, you need to bring the container in which it's defined in the current scope, like so:

fun test(intent: Intent) {
    with(SomeActivity.IntentOptions) {
        val someExtraValue = intent.someExtra
        intent.someExtra = "hello"
    }
}

Activity Companion

Optionally, you can use the provided ActivityCompanion (or SimpleActivityCompanion if you don't have any "intent options") to aid in creating intents for an Activity:

class SomeActivity : Activity() {

    companion object : ActivityCompanion<IntentOptions>(IntentOptions, SomeActivity::class)

    object IntentOptions {
        var Intent.someExtra by IntentExtra.String()
    }

    fun test() {
        val someExtraValue = intent.options { it.someExtra }
    }
}

fun test(context: Context) {
    SomeActivity.start(context) {
        it.someExtra = "hello"
    }
    // or
    val someActivityIntent = SomeActivity.intent(context) {
        it.someExtra = "hello"
    }
}

Custom types

Creating your own delegates is simple, as all building blocks are already provided.

For example to create a LocalDate (from Joda-Time), persisted as a String in an Intent:

import me.eugeniomarletti.extras.intent.IntentExtra
import me.eugeniomarletti.extras.intent.base.String
import org.joda.time.LocalDate

fun IntentExtra.LocalDate(name: String? = null, customPrefix: String? = null) =
    String(
        reader = { it?.let(LocalDate::parse) },
        writer = { it?.toString() },
        name = name,
        customPrefix = customPrefix)

Or in a Bundle:

import me.eugeniomarletti.extras.bundle.BundleExtra
import me.eugeniomarletti.extras.bundle.base.String
import org.joda.time.LocalDate

fun BundleExtra.LocalDate(name: String? = null, customPrefix: String? = null) =
    String(
        reader = { it?.let(LocalDate::parse) },
        writer = { it?.toString() },
        name = name,
        customPrefix = customPrefix)

The reader takes the persisted value in and outputs the custom type, while the writer does the opposite.

By defining the custom extensions on IntentExtra/BundleExtra, they will show up together with the basic types in the IDE autocomplete.

Nested types

There are cases when a type is composed of multiple simpler types, like the following example:

data class User(val id: Long, val email: String, val birthDay: LocalDate)

It's possible to compose multiple delegates to create a single "super delegate" that can read/write such a type:

import android.content.Intent
import me.eugeniomarletti.extras.DelegateProvider
import me.eugeniomarletti.extras.defaultDelegateName
import me.eugeniomarletti.extras.intent.IntentExtra
import me.eugeniomarletti.extras.intent.base.Long
import me.eugeniomarletti.extras.intent.base.String
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

fun IntentExtra.User(
    idName: String? = null,
    emailName: String? = null,
    birthdayName: String? = null,
    customPrefix: String? = null)
    =
    object : DelegateProvider<ReadWriteProperty<Intent, User?>> {

        override fun provideDelegate(thisRef: Any?, property: KProperty<*>) =

            object : ReadWriteProperty<Intent, User?> {

                private val namePrefix = property.defaultDelegateName(customPrefix)

                private var Intent.id by IntentExtra.Long(name = idName, customPrefix = namePrefix)
                private var Intent.email by IntentExtra.String(name = emailName, customPrefix = namePrefix)
                private var Intent.birthday by IntentExtra.LocalDate(name = birthdayName, customPrefix = namePrefix)

                override operator fun getValue(thisRef: Intent, property: KProperty<*>): User? {
                    val id = thisRef.id ?: return null
                    val email = thisRef.email ?: return null
                    val birthday = thisRef.birthday ?: return null
                    return User(id, email, birthday)
                }

                override operator fun setValue(thisRef: Intent, property: KProperty<*>, value: User?) {
                    thisRef.id = value?.id
                    thisRef.email = value?.email
                    thisRef.birthday = value?.birthDay
                }
            }
    }

An example usage could be:

package com.example

object IntentOptions {
    var Intent.currentUser by IntentExtra.User()
}

This will read/write 3 extras:

  • com.example.IntentOptions::currentUser::id with type Long
  • com.example.IntentOptions::currentUser::email with type String
  • com.example.IntentOptions::currentUser::birthday with type LocalDate (which is actually String)

Note that this is made possible by passing a custom prefix for the nested property names, which is going to be the default delegate name for the "super delegate" (in this case com.example.IntentOptions::currentUser).

The extra names can also be specified explicitly if necessary.

Download

Note that this is using Kotlin 1.1.2-3.

Add the following to the build.gradle:

repositories {
    jcenter()
}
dependencies {
    compile 'me.eugeniomarletti:android-extras-delegates:1.0.5'
}

android-extras-delegates's People

Contributors

takhion avatar cypressious avatar

Watchers

Al B. 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.