In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics are similar, there are some stylistic conventions on when to prefer one to another.
Prefer a property over a function when the underlying algorithm:
does not throw
is cheap to calculate (or cached on the first run)
returns the same result over invocations if the object state hasn’t changed
Using List result type we can only return all the values at once. To represent the stream of values that are being asynchronously computed we can use Flow type similarly to the Sequence type for synchronously computed values:
Right click res -> New -> Android Resource Directory, select anim and name it anim Right click res/anim -> New -> Android Resource file, name it bounce
Android 8.0 (API level 26) and Android Support Library 26 introduce support for APIs to request fonts from a provider application instead of bundling files into the APK or letting the APK download fonts. The feature is available on devices running Android API versions 14 and higher through the Support Library 26
Before
Select File -> New -> Folder -> Assets Folder to create src/main/assets/fonts
1 2
al myTypeface = Typeface.createFromAsset(assets, "fonts/myFont.ttf") myTextView.typeface = myTypeface
In res
Create font directory
Right click res -> New -> Android Resource Directory, select font and name the folder font
Add custom fonts to res/font folder. Note that name must be lower case and underscore, like opensans_extrabolditalic.ttf
Right click res/font -> New -> Font resource file to create font family
With structured concurrency async coroutine builder became an extension on CoroutineScope just like launch did. You cannot simply write async { … } anymore, you have to provide a scope. A proper example of parallel decomposition becomes:
coroutineScope function can be used to create a custom scope that suspends and only completes when all coroutines launched within that scope complete. If any of the children coroutines within the coroutineScope throws an exception, all other running sibling coroutines gets cancelled and this exception is propagated up the hierarchy. If the parent coroutine at the top of the hierarchy does not handle this error, it will also be cancelled.
Awaits for completion of given deferred values without blocking a thread and resumes normally with the list of values when all deferred computations are complete or resumes with the first thrown exception if any of computations complete exceptionally including cancellation.
This function is not equivalent to deferreds.map { it.await() } which fails only when it sequentially gets to wait for the failing deferred, while this awaitAll fails immediately as soon as any of the deferreds fail.
This suspending function is cancellable. If the Job of the current coroutine is cancelled or completed while this suspending function is waiting, this function immediately resumes with CancellationException.
dataclassResponseData( @field:Json(name="posts") val posts: Posts )
dataclassPosts( @field:Json(name="edges") val edges: List<Edge> )
dataclassEdge( @field:Json(name="node") val node: Item )
dataclassItem( @field:Json(name="id") val id: String, @field:Json(name="name") val name: String, @field:Json(name="url") val url: String, @field:Json(name="tagline") val tagline: String, @field:Json(name="featuredAt") val featuredAt: String, @field:Json(name="votesCount") val votesCount: Int, @field:Json(name="commentsCount") val commentsCount: Int, @field:Json(name="thumbnail") val thumbnail: Thumbnail )
dataclassThumbnail( @field:Json(name="url") val ur: String )
The liveData building block serves as a structured concurrency primitive between coroutines and LiveData. The code block starts executing when LiveData becomes active and is automatically canceled after a configurable timeout when the LiveData becomes inactive.
NavigationUI also provides helpers for tying destinations to menu-driven UI components. NavigationUI contains a helper method, onNavDestinationSelected(), which takes a MenuItem along with the NavController that hosts the associated destination. If the id of the MenuItem matches the id of the destination, the NavController can then navigate to that destination.
Add a navigation drawer
The drawer icon is displayed on all top-level destinations that use a DrawerLayout. Top-level destinations are the root-level destinations of your app. They do not display an Up button in the app bar.
In terms of tests, we usually have files for unit test, UI test, integeration test and mock.
Out of sight, out of mind.
Unit tests are for checking specific functions and classes, it’s more convenient to browse them side by side with source file. For example in Javascript, Kotlin and Swift
As you know, in the Pragmatic Programmer, section Your Knowledge Portfolio, it is said that
Learn at least one new language every year. Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut. Additionally, learning many languages is far easier now, thanks to the wealth of freely available software on the Internet
I see learning programming languages as a chance to open up my horizon and learn some new concepts. It also encourage good habit like immutability, composition, modulation, …
I’d like to review some of the features of all the languages I have played with. Some are useful, some just make me interested or say “wow”
Curly braces
Each language can have its own style of grouping block of code, but I myself like the curly braces the most, which are cute :]
Some like C, Java, Swift, … use curly braces
Swift
init(total: Double, taxPct: Double) {
self.total = total
self.taxPct = taxPct
subtotal = total / (taxPct + 1)
}
Some like Haskell, Python, … use indentation
Haskell
bmiTell :: (RealFloat a) => a -> String
bmiTell bmi
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
Some like Elixir use keyword list
ELixir
if false, do: :this, else: :that
Named parameter
Language like Objective C, Swift offer named parameter, which make it easier to reason about a function call
func sayHello(to person: String, and anotherPerson: String) -> String {
return "Hello \(person) and \(anotherPerson)!"
}
Explicit type
Language like C, Swift, Java, … have type information in parameter and in return, which make it easier to reason about a function call
Languages like Haskell, Python, Elixir, support list comprehension
Elixir
iex> for n <- [1, 2, 3, 4], do: n * n
[1, 4, 9, 16]
First class function
I enjoy functional programming, so first class function support in Javascript, Swift, Haskell, Elixir, … really make me happy
Haskell
zipWith' (*) (replicate 5 2) [1..]
Curry
Currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application)
Language like Swift 2, Haskell, … have curry by default. Some like Javascript can use libraries (Lodash, …) to achieve this. In Haskell, every function officially only takes one parameter.
The |> symbol used in the snippet above is the pipe operator: it simply takes the output from the expression on its left side and passes it as the first argument to the function call on its right side
Haskell often takes advantage of this custom -: operator Haskell
x -: f = f x
(0,0) -: landLeft 1 -: landRight 1 -: landLeft 2
Functor, Applicative Functor, Monoid, Monad
I really like enjoy Haskell because of these typeclasses. It realizes common pattern (map, apply, join, bind, …) with comptutational context. It really enlightens me when I find that function is a Monad as well (you should read the Reader monad)
Haskell
instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f = f x
fail _ = Nothing
landLeft :: Birds -> Pole -> Maybe Pole
landLeft n (left,right)
| abs ((left + n) - right) < 4 = Just (left + n, right)
| otherwise = Nothing
landRight :: Birds -> Pole -> Maybe Pole
landRight n (left,right)
| abs (left - (right + n)) < 4 = Just (left, right + n)
| otherwise = Nothing
ghci> return (0,0) >>= landLeft 1 >>= banana >>= landRight 1
Nothing
List comprehension in Haskell is just syntactic sugar for using lis as Monad Haskell
enum Result<T> {
case Value(T)
case Error(NSError)
}
extension Result {
func map<U>(f: T -> U) -> Result<U> {
switch self {
case let .Value(value):
return Result<U>.Value(f(value))
case let .Error(error):
return Result<U>.Error(error)
}
}
}
extension Result {
static func flatten<T>(result: Result<Result<T>>) -> Result<T> {
switch result {
case let .Value(innerResult):
return innerResult
case let .Error(error):
return Result<T>.Error(error)
}
}
}
extension Result {
func flatMap<U>(f: T -> Result<U>) -> Result<U> {
return Result.flatten(map(f))
}
}
Trait and mixin
Languages like Scala, … support trait
Similar to interfaces in Java, traits are used to define object types by specifying the signature of the supported methods. Unlike Java, Scala allows traits to be partially implemented; i.e. it is possible to define default implementations for some methods
Scala
trait Similarity {
def isSimilar(x: Any): Boolean
def isNotSimilar(x: Any): Boolean = !isSimilar(x)
}
class Point(xc: Int, yc: Int) extends Similarity {
var x: Int = xc
var y: Int = yc
def isSimilar(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x
}
module Greetings
def hello
puts "Hello!"
end
def bonjour
puts "Bonjour!"
end
def hola
puts "Hola!"
end
end
class User
include Greetings
end
Delegate property
There are certain common kinds of properties that would be very nice to implement once and for all like lazy, observable and storing. An example is in Kotlin
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
Where to go from here
Hope you find something interesting. Each language has its own pros and is designed for specific purpose. So no list will be enough to cover them all.
To take a quick peek into other programming languages, I find Learn in One Video by Derek very helpful.
There are things that intrigue us every day like Swift initialization rule make it explicit when using initializer, Go goroutine and channel for concurrent code, Elixir process for easy concurrent and message communication. You’ll be amazed by how process encapsulates state, Haskell data type encourages immutability and thread safe code, Elixir macro for great extension of the language. The best way to to learn is to use and dive into the languages often.
Each language and platform has its own coding style guide. This goes true when it comes to abbreviations. I’ve had some debates about whether to use JSON or Json, URL or Url, HTTP or Http.
I personally prefer camelCase, so I’m very happy to see that Kotlin is on my side. See Kotlin Style guide, I think this guide should be applied in other languages, such as Swift 😛
Sometimes there is more than one reasonable way to convert an English phrase into camel case, such as when acronyms or unusual constructs like “IPv6” or “iOS” are present. To improve predictability, use the following scheme.
Beginning with the prose form of the name:
Convert the phrase to plain ASCII and remove any apostrophes. For example, “Müller’s algorithm” might become “Muellers algorithm”.
Divide this result into words, splitting on spaces and any remaining punctuation (typically hyphens).
Recommended: if any word already has a conventional camel-case appearance in common usage, split this into its constituent parts (e.g., “AdWords” becomes “ad words”). Note that a word such as “iOS” is not really in camel case per se; it defies any convention, so this recommendation does not apply.
Now lowercase everything (including acronyms), then uppercase only the first character of:
…each word, to yield pascal case, or
…each word except the first, to yield camel case
Finally, join all the words into a single identifier.
Note that the casing of the original words is almost entirely disregarded.
Prose form
Correct
Incorrect
“XML Http Request”
XmlHttpRequest
XMLHTTPRequest
“new customer ID”
newCustomerId
newCustomerID
“inner stopwatch”
innerStopwatch
innerStopWatch
“supports IPv6 on iOS”
supportsIpv6OnIos
supportsIPv6OnIOS
“YouTube importer”
YouTubeImporterYoutubeImporter*
About iOS or IOS, I think I would go with IOS. I think React Native thinks so too
NavigatorIOS looks and feels just like UINavigationController, because it is actually built on top of it.
funhtml(init: HTML.() -> Unit): HTML { val html = HTML() // create the receiver object html.init() // pass the receiver object to the lambda return html }
html { // lambda with receiver begins here body() // calling a method on the receiver object }
To continue the analogy, await() can be a suspending function (hence also callable from within an async {} block) that suspends a coroutine until some computation is done and returns its result:
We are using the delay() function that’s like Thread.sleep(), but better: it doesn’t block a thread, but only suspends the coroutine itself. The thread is returned to the pool while the coroutine is waiting, and when the waiting is done, the coroutine resumes on a free thread in the pool.
await() can not be called outside a coroutine, because it needs to suspend until the computation finishes, and only coroutines can suspend in a non-blocking way
What does suspend function mean in Kotlin Coroutine 🤔
Basically, coroutines are computations that can be suspended without blocking a thread
I heard people often say “suspend function”. But I think it is the coroutine who gets suspended because it is waiting for the function to finished? “suspend” usually means “cease operation”, in this case the coroutine is idle.
To continue the analogy, await() can be a suspending function (hence also callable from within an async {} block) that suspends a coroutine until some computation is done and returns its result:
1 2 3 4 5 6
async { // Here I call it the outer async coroutine ... // Here I call computation the inner coroutine val result = computation.await() ... }
🤔 It says “that suspends a coroutine until some computation is done”, but coroutine is like a lightweight thread. So if the coroutine is suspended, how can the computation is done ?
We see await is called on computation, so it might be async that returns Deferred, which means it can start another coroutine
🤔 The quote say that suspends a coroutine. Does it mean suspend the outer async coroutine, or suspend the inner computation coroutine?
Does suspend mean that while outer async coroutine is waiting (await) for the inner computation coroutine to finish, it (the outer async coroutine) idles (hence the name suspend) and returns thread to the thread pool, and when the child computation coroutine finishes, it (the outer async coroutine) wakes up, takes another thread from the pool and continues?
Conceptually, async is just like launch. It starts a separate coroutine which is a light-weight thread that works concurrently with all the other coroutines. The difference is that launch returns a Job and does not carry any resulting value, while async returns a Deferred – a light-weight non-blocking future that represents a promise to provide a result later. You can use .await() on a deferred value to get its eventual result, but Deferred is also a Job, so you can cancel it if needed.
1 2 3 4 5 6 7 8
funmain(args: Array<String>) = runBlocking<Unit> { val time = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") }
There is a laziness option to async using an optional start parameter with a value of CoroutineStart.LAZY. It starts coroutine only when its result is needed by some await or if a start function is invoked. Run the following example that differs from the previous one only by this option:
1 2 3 4 5 6 7 8
funmain(args: Array<String>) = runBlocking<Unit> { val time = measureTimeMillis { val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() } val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") }
What is the difference between launch/join and async/await in Kotlin coroutines
So you can think of coroutine as something that manages thread in a very efficient way.
🐤 launch
1 2 3 4 5 6 7 8
funmain(args: Array<String>) { launch { // launch new coroutine in background and continue delay(1000L) // non-blocking delay for 1 second (default time unit is ms) println("World!") // print after delay } println("Hello,") // main thread continues while coroutine is delayed Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive }
So launch starts a background thread, does something, and returns a token immediately as Job. You can call join on this Job to block until this launch thread completes
1 2 3 4 5 6 7 8
funmain(args: Array<String>) = runBlocking<Unit> { val job = launch { // launch new coroutine and keep a reference to its Job delay(1000L) println("World!") } println("Hello,") job.join() // wait until child coroutine completes }
🦆 async
Conceptually, async is just like launch. It starts a separate coroutine which is a light-weight thread that works concurrently with all the other coroutines. The difference is that launch returns a Job and does not carry any resulting value, while async returns a Deferred – a light-weight non-blocking future that represents a promise to provide a result later.
So async starts a background thread, does something, and returns a token immediately as Deferred.
1 2 3 4 5 6 7 8
funmain(args: Array<String>) = runBlocking<Unit> { val time = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") }
You can use .await() on a deferred value to get its eventual result, but Deferred is also a Job, so you can cancel it if needed.
There is a laziness option to async using an optional start parameter with a value of CoroutineStart.LAZY. It starts coroutine only when its result is needed by some await or if a start function is invoked.
Understand Kotlin Coroutines on Android (Google I/O’19)
/** * Calls the specified function [block] with `this` value as its receiver and returns `this` value. */ @kotlin.internal.InlineOnly publicinlinefun<T> T.apply(block: T.() -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() returnthis }
/** * Calls the specified function [block] with `this` value as its argument and returns its result. */ @kotlin.internal.InlineOnly publicinlinefun<T, R> T.let(block: (T) -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }
Kotlin provides the ability to call a function literal with a specified receiver object. Inside the body of the function literal, you can call methods on that receiver object without any additional qualifiers. This is similar to extension functions, which allow you to access members of the receiver object inside the body of the function
There’s always need for communication, right 😉 Suppose we have OnboardingActivity that has several OnboardingFragment. Each Fragment has a startButton telling that the onboarding flow has finished, and only the last Fragment shows this button.
Here are several ways you can do that
1. EventBus 🙄
Nearly all articles I found propose this https://github.com/greenrobot/EventBus, but I personally don’t like this idea because components are loosely coupled, every component and broadcast can listen to event from a singleton, which makes it very hard to reason when the project scales
// Listen should return an Observable and not the publisher // Using ofType we filter only events that match that class type fun <T> listen(eventType: Class<T>): Observable<T> = publisher.ofType(eventType) }
This is advised here Communicating with Other Fragments. Basically you define an interface OnboardingFragmentDelegate that whoever conforms to that, can be informed by the Fragment of events. This is similar to Delegate pattern in iOS 😉
We can learn from Share data between fragments to to communication between Fragment and Activity, by using a shared ViewModel that is scoped to the activity. This is a bit overkill
1 2 3
classOnboardingSharedViewModel: ViewModel() { val finish = MutableLiveData<Unit>() }