oligazar
7/8/2017 - 12:39 PM

Kotlin tricks

Kotlin tricks

 print(nullableList
                .run { // calls methods on 'this', return method's result
                    toMutableList()
                    .apply{ add(9)} } // calls methods on 'this' and returns 'this'
                .groupBy { it % 3 })


    sealed class Payloads {
        data class Favorite (var favorited: Boolean): Payloads()
        data class Retweet (var retweeted: Boolean): Payloads()
        data class CountUpdate (
                var favorites: Long,
                var retweets: Long,
                var replies: Long): Payloads()
    }

    fun onBindViewHolder() {
        payloads.forEach {
            when (it) {
                is Payloads.Favorite -> { holder.favouriteIcon.isActivated = it.favorited}
                // ...
            }
        }
    }


    class PaymentRobot {
        fun amount(value: Long) { }
        fun send() {}
    }

    fun payment(body: PaymentRobot.() -> Unit) = PaymentRobot().apply(body)

    @Test
    fun sendMoney() {
        payment {
            amount(10)
            send()
        }
    }
package ds.wifimagicswitcher.prefs

import android.content.Context
import android.content.SharedPreferences
import ds.wifimagicswitcher.utils.T
import kotlin.properties.ReadWriteProperty

// https://gist.github.com/deviant-studio/85bbd34beffe33372c2d
object KotlinPrefsSetup {
	@Volatile var isBatching = false
	lateinit var prefs: SharedPreferences
	lateinit var edit: SharedPreferences.Editor
	/**
	 * Run it on App start
	 */
	fun init(ctx: Context, name: String) {
		prefs = ctx.getSharedPreferences(name, Context.MODE_PRIVATE)
		edit = prefs.edit()
	}
}

@Synchronized fun prefsBatch(f: () -> Unit) {
	KotlinPrefsSetup.isBatching = true
	f()
	KotlinPrefsSetup.isBatching = false
	KotlinPrefsSetup.edit.apply()
}

fun prefsKey<T>(default: T): PrefsDelegate<T> = PrefsDelegate(default)

class PrefsDelegate<T>(val default: T) : ReadWriteProperty<Any?, T> {

	var value: T = default

	@Suppress("unchecked_cast")
	override fun get(thisRef: Any?, property: PropertyMetadata): T {
		val n = property.name
		val prefs = KotlinPrefsSetup.prefs
		when (value) {
			is String -> return prefs.getString(n, default as String) as T
			is Int -> return prefs.getInt(n, default as Int) as T
			is Long -> return prefs.getLong(n, default as Long) as T
			is Float -> return prefs.getFloat(n, default as Float) as T
			is Boolean -> return prefs.getBoolean(n, default as Boolean) as T
			is Set<*> -> return prefs.getStringSet(n, default as Set<String>) as T
			else -> throw IllegalArgumentException()
		}
	}

	@Suppress("unchecked_cast")
	override fun set(thisRef: Any?, property: PropertyMetadata, value: T) {
		this.value = value
		val n = property.name
		val e = KotlinPrefsSetup.edit
		when (value) {
			is String -> e.putString(n, value)
			is Int -> e.putInt(n, value)
			is Long -> e.putLong(n, value)
			is Float -> e.putFloat(n, value)
			is Boolean -> e.putBoolean(n, value)
			is Set<*> -> e.putStringSet(n, value as Set<String>)
			else -> throw IllegalArgumentException()
		}

		if (!KotlinPrefsSetup.isBatching)
			e.apply()
	}

}
// Return the set of products that were ordered by every customer
fun Shop.getSetOfProductsOrderedByEveryCustomer(): Set<Product> {
    val setOfOrderedProducts = customers.flatMap { it.orders.flatMap { it.products }}.toSet()
 	// return setOfOrderedProducts.filter { item ->
    //     customers.all { it.orders.flatMap { it.products }.contains(item) }
    // }.toSet()
    return customers.fold (setOfOrderedProducts) { orderedByAll, customer ->
        orderedByAll.intersect( customer.orders.flatMap { it.products }.toSet() )
    }
}

// imageView.loadFrom(url)
// 10.toPx(context)

class LazyProperty(val initializer: () -> Int) {
    
   // val lazy: Int by lazy {
   //         initializer()
   //     }
    var value: Int? = null
    val lazy: Int
    	get() {
            if (value == null) {
                value = initializer()
            }
            return value!!
        }
}


    @RequiresApi(Build.VERSION_CODES.KITKAT)
    class MyListener: Transition.TransitionListener by EmptyTransitionListener {
        override fun onTransitionCancel(transition: Transition?) {
            
        }
    }

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    object EmptyTransitionListener: Transition.TransitionListener {
        override fun onTransitionEnd(transition: Transition?) { }
        override fun onTransitionResume(transition: Transition?) { }
        override fun onTransitionPause(transition: Transition?) { }
        override fun onTransitionCancel(transition: Transition?) { }
        override fun onTransitionStart(transition: Transition?) { }
    }
fun usage() {
      val views = LinearLayout(activity)
      views.forEach { view ->
          TODO()
      }
      val first = views[0]
      views -= first
      views += first
      if (view in views) TODO()
      if (BuildConfig.DEBUG) Log.d("Test", ": View count: ${views.size}")

      val visibleHeight = views.children()
              .filter { it.visibility == View.VISIBLE }
              .sumBy { it.measuredHeight }

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
          val result = trace("foo") {
              TODO("expensive calculation")
          }
      }
  }

  // note.1: Extension methods will desugar into static method where the view group is a first parameter
  // note.2: without inline lambda would cause anonymous class to be created, which would encapsulate everything
  // to avoid that - use inline keyword. So method becomes free to use
  inline fun ViewGroup.forEach(action: (View) -> Unit) {
      for (index in 0 until childCount) {
          action(getChildAt(index))
      }
  }

  // Transform our view group into iterable
  fun ViewGroup.children() = object: Iterable<View> {
      override fun iterator()= object: Iterator<View> {
          var index = 0
          override fun hasNext() = index < childCount
          override fun next() = getChildAt(index++)
      }
  }

  operator fun ViewGroup.get(index: Int): View? = getChildAt(index)
  operator fun ViewGroup.minusAssign(child: View?) = removeView(child)
  operator fun ViewGroup.plusAssign(child: View?) = addView(child)
  operator fun ViewGroup.contains(child: View?) = indexOfChild(child) != -1
  val ViewGroup.size: Int
      get() = childCount

  @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
  inline fun <T>trace(sectionName: String, body: () -> T): T {
      Trace.beginSection(sectionName)
      try {
          return body()
      } finally {
          Trace.endSection()
      }
  }

  fun doSomethingToDb(db: SQLiteDatabase) {

      db.transaction {
          delete("users", "first_name = ?", arrayOf("jake"))
      }
  }

  class UserPersistance(private val db: SQLiteDatabase) {
      // property delegation
      private val deleteByFirstName by lazy {
          db.compileStatement("DELETE FROM users WHERE first_name = ?")
      }

      fun deleteByFirstName(name: String) {
          db.transaction {
              deleteByFirstName.bindString(1, name)
              deleteByFirstName.execute()
          }
      }
  }


// Lamba with recievers - is kinda lambda extension function
inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.() -> Unit) {
    beginTransaction()
    try {
        body()
        setTransactionSuccessful()
    } finally {
        endTransaction()
    }
}


    @Suppress("UNCHECKED_CAST")
    private fun <T> bindView(id: Int) = object: kotlin.properties.ReadOnlyProperty<Any?, T> {
        override fun getValue(thisRef: Any?, property: KProperty<*>) = findViewById(id) as T
    }