preface

Recently, Kotlin’s voice has become louder and louder. A few days ago, Google IO in 9012 officially promoted Kotlin from First class to Kotlin_first. I have also been in touch with Kotlin for a period of time, which gives me the impression of simplicity and speed. Without the tedious findId, the application of higher-order functions, coupled with Kotlin’s null security, reduces the code crash rate even further.

Today, let’s introduce today’s protagonist, Anko

1.Anko

Anko is a powerful library developed by JetBrains, which is awesome. They developed Kotlin, intellij Idea, the most popular development tool, and AS is based on Idea. Anyway, Anko is an official Kotlin library that makes developing Android apps faster and easier, and makes writing code simpler and easier to read. It has multiple parts

  1. Anko Commons: a lightweight library full of helpers for intents, dialogs, logging and so on;
  2. Anko Layouts: a fast and type-safe way to write dynamic Android layouts;
  3. Anko SQLite: a query DSL and parser collection for Android SQLite;
  4. Anko Coroutines: utilities based on the kotlinx.coroutines library.

1.1 Usage

Add the dependent

dependencies {
    implementation "org.jetbrains.anko:anko:$anko_version"
}
Copy the code

This includes the above four sections, but you can also rely on just one, as follows:

dependencies {
    // Anko Commons
    implementation "org.jetbrains.anko:anko-commons:$anko_version"

    // Anko Layouts
    implementation "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
    implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"

    // Coroutine listeners for Anko Layouts
    implementation "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"
    implementation "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"

    // Anko SQLite
    implementation "org.jetbrains.anko:anko-sqlite:$anko_version"
}
Copy the code

Let’s take a look at each of these features.

2 AnkoCommons

AnkoCommons is a toolset for Android developers, including but not limited to the following

  1. Intents
  2. Dialogs and toasts
  3. Logging
  4. Resources and dimensions

2.1 the Intents

As mentioned earlier, the Commons library is a toolset, and Intents is mainly used to help simplify jumping between activities.

The traditional way Kotlin starts a new Activity is by creating an Intent, possibly passing some parameters, and passing the created Intent through the Context’s startActivity() method, like this:

val intent = Intent(this, SomeOtherActivity::class.java)
intent.putExtra("id", 5)
intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
Copy the code

All you need to use Anko is this:

startActivity(intentFor(“id” to 5).singleTop())

If you want to pass multiple arguments, you can do that too

startActivity<SomeOtherActivity>(
    "id" to 5,
    "city" to "Denpasar"
)
Copy the code

Of course, there are other actions on intEnts, such as making a call

2.2 Dialogs and toasts

This library is mainly used to quickly build dialogs and Toasts, including the following

  • Toast
  • SnackBar
  • Alert (Dialog)
  • Selectors
  • Progress dialogs

2.2.1 Toast

Anko gives us a much simpler use of Toast with just one line of code

toast("Hi there!")
toast(R.string.message)
longToast("Wow, such duration")
Copy the code

2.2.2 SnackBars

SnackBar is a new addition to the Android Support Library 22.2.0. It can be easily thought of as an enhanced Toast, or a lightweight Dialog. We can quickly create a snackbar with the following code.

view.snackbar("Hi there!")
view.snackbar(R.string.message)
view.longSnackbar("Wow, such duration")
view.snackbar("Action, reaction"."Click me!") { doStuff() }
Copy the code

So we need to pass in a View object, which could be any view object in the layout.

2.2.3 Alerts

Anko Alerts mainly includes the following functions:

  1. The Android default dialog
  2. The Android Appcompat AlertDialog
  3. Custom Dialog

To build an interactive Android default dialog, use the following code.

alert("Hi, I'm Roy"."Have you tried turning it off and on again?") {
    yesButton { toast("Oh...") }
    noButton {}
}.show()
Copy the code

The code is relatively simple, so I won’t explain it.

Anko also provides an AlertDialog implementation for Android Appcompat, as follows:

alert(Appcompat, "Some text message").show()
Copy the code

What, can’t you customize Dialog? How come, customizing dialogs is so easy

alert {
    customView {
        editText()
    }
}.show()
Copy the code

2.2.4 Selectors

We normally create a list Dialog like this:

  val listItems = arrayOf("Russia"."USA"."Japan"."Australia"// Pass array val listDialog: AlertDialog.Builder = AlertDialog.Builder(this) listDialog.setItems(listItems) { p0, p1 -> toast(p1) } val dialog: AlertDialog = listDialog.create() dialog.show() val window: Window = dialog.window val params: WindowManager.LayoutParams = window.attributes params.y = 45 * ScreenUtils.getScreenDensity().toInt() params.gravity = Gravity.TOP or Gravity.RIGHT params.width = ScreenUtils.getScreenWidth() / 2 params.height = ViewGroup.LayoutParams.WRAP_CONTENT window.attributes = paramsCopy the code

But we use Anko like this:

val countries = listOf("Russia"."USA"."Japan"."Australia"// Pass list selector("Where are you from?", countries, { dialogInterface, i ->
    toast("So you're living in ${countries[i]}, right?")})Copy the code

It just seems to simplify the dialog creation process.

2.2.5 Progress dialogs

Loading Dialg does not display progress

pressDialog("Please wait a minute."."Downloading...")
indeterminateProgressDialog("Fetching the data...")
Copy the code

2.3 Logging

Print the log helper.

The Android SDK provides the Android.util. Log class to provide some logging methods. These methods are useful, but we have to pass a Tag argument at a time, and the Tag information must be a String, which is a bit cumbersome. But now we can get rid of these annoying problems with the AnkoLogger class:

class SomeActivity : Activity(), AnkoLogger {
    fun someMethod() {
        info("Info message")
        debug(42) // .toString() method will be called automatically
    }
}
Copy the code

The default Tag name is the current class name (SomeActivity in this case), but this can be changed by overriding AnkoLogger’s loggerTag property and each method has two versions: plain and lazy (inlined)

1. Lazy:

info("String " + "concatenation")
info { "String " + "concatenation" }
Copy the code

2.plain:

class SomeActivity : Activity() {
    private val log = AnkoLogger(this.javaClass)
    private val logWithASpecificTag = AnkoLogger("my_tag")

    private fun someMethod() {
        log.warning("Big brother is watching you!")}}Copy the code

The above two methods are different implementations of tags.

The loggerTag attribute in AnkoLogger is compared as follows:

2.4 the Resources and dimensions

You can use Anko Resources and Dimensions in your project to simplify your code, for example, Color, Dimen, Color transparency, opaque, dip(dipValue), SP (spValue), etc. There is also an applyrecurshrink () method for controlling the actions of on-screen integrators:

  verticalLayout {
        textView{
            text = "EditText01"
            backgroundColor = 0xff000.opaque
            textSize = 14f
        }
        textView {
            text = "EditText02"BackgroundColor = 0x99.gry.opaque textSize = 23F}}. Applyrecurshrink {// If you are viewing groups, you can use ApplyRecurshrink for each Child View -> when(View){is TextView -> view.textColor = color.red}}Copy the code

3.Anko Layouts

We usually use XML files to write our layouts, but they have some disadvantages such as not being type-safe, not being null-safe, parsing XML files consumes more CPU and power, and so on. Anko Layout can use DSL(Domain Specific Language) to create our UI dynamically, and it is much more convenient than Java to create a Layout dynamically. It is much more concise and has a hierarchical relationship with XML to create a Layout, which makes it easier to read. (Official advantages)

Here’s an example:

verticalLayout {
    val name = editText()
    button("Say Hello") {
        onClick { toast("Hello, ${name.text}!")}}}Copy the code

The default controls do not meet our needs. For example, we can change the color and size of the font, set the width and height, and set the margin and padding values. So how to implement it is also very simple, because the logic and XML writing layout is the same. For example, the following implementation

val textView=textView("I'm a TextView"){
                textSize = sp(17).toFloat()
                textColor=0xff000.opaque
            }.lparams{
                margin=dip(10)
                height= dip(40)
                width= matchParent
            }
Copy the code

Is it easy to work with the Common library?

We don’t need setContentView here. I’ll just put it in the onCreate method.

When we created the UI above, we wrote the code to create the UI directly in the onCreate method, and of course, there’s another way to write it. We create an inner class that implements the AnkoComponent interface and override the createView method that returns a View, the layout we created. Modify the following

class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle? , persistentState: PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) MyActivityUI().setContentView(this) } } class MyActivityUI : AnkoComponent<MyActivity> { override fun createView(ui: AnkoContext<MyActivity>) = with(ui) { verticalLayout { val name = editText() button("Say Hello") {
                onClick { ctx.toast("Hello, ${name.text}!")}}}}}Copy the code

Now we compile and run and find that the interface is the same as the layout file. But it has a performance advantage, in fact, I don’t see the performance advantage. However, this DSL is really easy to read and easy to use. In the code above, you may have noticed dip(10), which stands for converting 10DP to pixels, as an extension function of Anko. If you read the Anko source code, you’ll see a lot of use of extension functions. This is one of the strengths of the Kotlin language.

Here is a brief introduction to the use and advantages of Layout. But I think you will not necessarily use it in the actual development, because it is unacceptable not to use visualization. But that’s a matter of opinion.

4.Anko SQLite: a query DSL and parser collection for Android SQLite;

Anko SQLite is a domain-specific language for query parsing SQLite

Disadvantages of SQLite:

  1. Too much template code to implement;
  2. Implementing SQL commands through strings is error-prone and cannot be checked during compilation.
  3. Manually shut down the database each time;
  4. Threading and synchronous access issues;

The more complex your database becomes, the more problems are exposed. So it’s no wonder that many people opt for ORM or NoSQL, but the convenience comes at the expense of increasing application size and number of methods.

If you’re planning to use Kotlin to develop Android applications, you can now use Anko SQLite to do SQLite operations with ease. For example, you can do away with cumbersome cursors and ContentValues, and built-in security mechanisms to ensure that the database can be closed after all code is executed.

Implement the database helper class by inheriting the ManagedSQLiteOpenHelper class. The recommended approach is to follow the official implementation:

class DatabaseHelper(ctx: Context) : ManagedSQLiteOpenHelper(ctx, "LibraryDatabase", null, 1) {
  companion object {
    private var instance: DatabaseHelper? = null

    @Synchronized
    fun Instance(context: Context): DatabaseHelper {
      if (instance == null) {
        instance = DatabaseHelper(context.applicationContext)
      }
      return instance!!
    }
  }

  override fun onCreate(database: SQLiteDatabase) {
    createTable(Book.TABLE_NAME, true, Book.COLUMN_ID to INTEGER + PRIMARY_KEY, Book.COLUMN_TITLE to TEXT, Book.COLUMN_AUTHOR to TEXT)
  }

  override fun onUpgrade(database: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
    dropTable(Book.TABLE_NAME, true)}}Copy the code

The recommended way to access the database is through dependency injection, or by adding an extension to the Context:

val Context.database: DatabaseHelper
  get() = DatabaseHelper.Instance(applicationContext)
Copy the code

Here is a simple Model class:

data class Book(val id: Int, val title: String, val author: String) {
  companion object {
    val Book.COLUMN_ID = "id"
    val TABLE_NAME = "books"
    val COLUMN_TITLE = "title"
    val COLUMN_AUTHOR = "author"}}Copy the code

When the database is ready, you can use the use method. Such as:

database.use {
    insert(Book.TABLE_NAME, Book.COLUMN_ID to 1, Book.COLUMN_TITLE to "2666", Book.COLUMN_AUTHOR to "Roberto Bolano")}Copy the code

Finally, let’s compare the sizes of common libraries:

Kotlin Runtim (method count: 6298, DEX size: 1117 KB) and Anko Commons Module (Method Count: 982, DEX Size: 174 KB). So if you’re using Kotlin, Anko SQLite doesn’t actually increase in size as much as the chart shows.

Therefore, if you are developing with Kotlin and the database complexity is not high, Anko SQLite is the first choice. However, if the database structure is very complex and DAO and SQL queries can become painful, ORM and NoSQL are the preferred solution.

5.Anko Coroutines: utilities based on the kotlinx.coroutines library.

Kotlin coroutines Are essentially lightweight threads that allow us to write asynchronous requests synchronously instead of Callback.

doAsync(UI) {
    val data: Deferred<Data> = bg {
		// Runs in background
		getData()
    }

    // This code is executed on the UI thread
    showData(data.await())
}
Copy the code

We can use bg () to perform time-consuming operations on the new thread and wait for the results to return before performing operations on the UI thread.

See the official documentation for the coroutine tutorial

Kotlin coroutines

6. Summary

Anko is an official Kotlin library that makes developing Android apps faster and easier, and makes writing code simpler, clearer and easier to read. It mainly includes the following parts.

  1. Anko Commons: a lightweight library full of helpers for intents, dialogs, logging and so on;
  2. Anko Layouts: a fast and type-safe way to write dynamic Android layouts;
  3. Anko SQLite: a query DSL and parser collection for Android SQLite;
  4. Anko Coroutines: utilities based on the kotlinx.coroutines library.

The Anko library is very easy to use, with DSLS and extension functions designed inside.

Read this article about DSLS

Kotlin’s Beauty – DSL

You can read this article about extension functions

Kotlin extension function details and applications