Kotlin's simple and practical method uses Kotlin to develop Android applications elegantly


The 2017 Google I/O Worldwide Developers Conference was held from May 17 to 19, 2017 at the Shoreline Amphitheatre in Mountain View, California, USA. At this conference, Google fully introduced the application of artificial intelligence in various fields, and also launched the iOS version of the voice assistant, the latest version of Android O and the series of VR glasses. The most important one is the Google I/O conference. The Kotlin programming language is used as the first-level language for Android development. This language has been open sourced since 2010. However, Google did not propose to use it as the first-level language for Android client development until this year's I/O conference. Presumably Google is also Have some ideas!

Today's article will take you to learn to use Kotlin to develop Android applications, and compare it with our traditional language Java, so that you can really feel its beauty and elegance.

configure

Project gradle file

apply plugin: 'com.android.application'
apply plugin:'kotlin-android'
apply plugin:'kotlin-android-extensions'

dependencies {
    classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.1'
}

app Gradle file:

compile 'org.jetbrains.kotlin:kotlin-stdlib:1.1.1'
compile 'org.jetbrains.anko:anko-sdk25:0.10.0-beta-1'// sdk15, sdk19, sdk21, sdk23 are also available
compile 'org.jetbrains.anko:anko-appcompat-v7:0.10.0-beta-1'

Anko

Through the above configuration, you will find that the dependencies of anko are introduced. Anko is a powerful library developed by JetBrains. Speaking of JetBrains, it is awesome. The Kotlin language is developed by them. The most popular development tool intellij idea is developed by them, and AS is also based on IDEA. Well, let’s get down to business, Anko is a Kotlin library officially developed by Kotlin that makes developing Android applications faster and easier, and makes the code we write simpler, clearer and easier to read. It consists of multiple parts as follows

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

So next, we will use the code to understand the advantages of developing Android in Kotlin language.

Never use findViewById again

Anyone who has done Android development knows that there are too many layout files written, and findViewById is also a lot of work, and it is necessary to declare variables first, and then forcefully convert them into our controls in findViewById. The general usage is as follows

TextView username;
username=(TextView)findViewById(R.id.user);

username.setText("我是一个TextView");

Sometimes I feel sick when I write, maybe some people say that it is not a library with some annotations, such as butterknife, when we use annotations, we don't need to findViewById, the way to use is as follows

@BindView(R.id.user)
TextView username;

username.setText("我是一个TextView");

This is indeed the case. After using annotations, it does give us a little less work, but it is still not the simplest. The simplest thing is that we can directly assign values ​​to the control whose id is user. Maybe you will feel this is a bit incredible. But Kotlin does. We can directly write

user.text="我是一个TextView"

Seeing this, do you have a feeling of seeing each other late, too Tama's simplicity. user is the id declared in our layout file, .text is just like setText(). In Kotlin language, we can't see the set/get method like in Java. It should be noted that when we want to use it in this way (without findingViewById, we need to add apply plugin: 'kotlin-android-extensions' to gradle directly using xml controls), we need to add the following code

//activity_login就是我们的布局
import kotlinx.android.synthetic.main.activity_login.*

Anko Layout

Usually we use xml file to write our layout, but it has some disadvantages such as not type safe, not null safe, parsing xml file consumes more CPU and power and so on. Anko Layout can use DSL to dynamically create our UI, and it is much more convenient than we use Java to dynamically create layouts, mainly more concise, and it has a hierarchical relationship with xml to create layouts, which makes it easier for us to read.

verticalLayout {
            val textView=textView("我是一个TextView")
            val name = editText("EditText")
            button("Button") {
                onClick { toast("${name.text}!") }
            }
        }

We can remove setContentView in the OnCreate method, and then add the above code to display the effect as shown below, that is, a vertical linear layout, with a TextView, an EditText, and a Button. And there is a click event in Button, when clicked, the content of EditText will be
displayed as toast.

Is the above code very simple and easy to understand? Of course, the default controls cannot meet our needs. For example, we will change the color and size of the font, set the width and height, and set the margin and padding values. How to implement it? , of course, it is also very simple, because its logic and xml writing layout are a routine. For example the following implementation

val textView=textView("我是一个TextView"){
                textSize = sp(17).toFloat()
                textColor=context.resources.getColor(R.color.red)
            }.lparams{
                margin=dip(10)
                height= dip(40)
                width= matchParent
            }

I think I don't need to explain the above code, you should see the effect of the control implementation. Because its attribute corresponds to the name of the attribute we set in xml.

In the process of creating the UI above, we directly wrote the code for creating the UI in the onCreate method. Of course, there is another way to write it. We create an inner class that implements the AnkoComponent interface and override the createView method, which returns a View, which is the layout we created. Modify as follows

inner class UI : AnkoComponent<LoginActivity> {
        override fun createView(ui: AnkoContext<LoginActivity>): View {
           return with(ui){
               verticalLayout {
                   val textView=textView("我是一个TextView"){
                       textSize = sp(17).toFloat()
                       textColor=context.resources.getColor(R.color.red)
                   }.lparams{
                       margin=dip(10)
                       height= dip(40)
                       width= matchParent
                   }
                   val name = editText("EditText")
                   button("Button") {
                        onClick { view ->
                            toast("Hello, ${name.text}!")
                        }
                   }
               }
           }
        }
    }

Then add a line of code to the onCreate method to create our layout page. as follows

UI().setContentView(this@LoginActivity)

Now we compile and run, and find that the effect is the same as the interface written in the layout file. But its performance is advantageous, in fact, it did not find the performance advantage. Anyway, this DSL is really easy to read and easy to use. In the above code, you may have noticed dip(10), which means to convert 10dp to pixels, which is Anko's extension function, said extension function , If you read the source code of Anko, we find that there is a lot of use of extension functions, which is also one of the advantages of the Kotlin language. Really powerful, such as dip extension (extract View extension)

inline fun View.dip(value: Int): Int = context.dip(value)
fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()

In the above resources.displayMetrics.density and our Java getResources().getDisplayMetrics().density is an effect, but you will feel more comfortable than Java writing, anyway, I feel so.

In the above we added a click event to Button, we found that it supports lambda expressions. If we want to display a Toast, we only need toast("content"), is it very concise? In fact, it is also an extension function, which implements

inline fun AnkoContext<*>.toast(message: CharSequence) = ctx.toast(message)
fun Context.toast(message: CharSequence) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

Of course, creating a dialog is still very simple, as follows

            alert ("我是Dialog"){
                      yesButton { toast("yes")}
                      noButton {  toast("no")}
                    }.show()

It really makes me feel better the more I look at it, haha. Here's another powerful, yet very simple, very simple and concise piece of code to implement.

        doAsync {
            //后台执行代码
            uiThread { 
            //UI线程
            toast("线程${Thread.currentThread().name}") }
        }

This piece of code implements the effect of AsyncTask, but you should find that it is much simpler than the Java implementation. Of course, unless you are colorblind, you will see the simplicity.

If you use Kotlin to develop Android for a period of time, you will find that it reduces the amount of code for us a lot. Of course, more advantages and usage need to be explored by ourselves. Believe it will surprise you after exploring.

Implement a simple login interface

The interface is simple, pseudocode

<LinearLayout>

<ImageView/>

<LinearLayout> <ImageView/><EditText账号/><LinearLayout>

<LinearLayout> <ImageView/><EditText密码/><LinearLayout>

<Button 登录/>

<LinearLayout> <CheckBox 记住密码/><TextView 隐私协议xieu/><LinearLayout>

<TextView/>

</LinearLayout>

It doesn't look complicated, so the xml implementation code is not posted here. If you want to see the xml implementation, you can click and check , then let's just look at Anko's implementation of this layout in Kotlin code.

  lateinit var et_account: EditText
    lateinit var et_password: EditText
    inner class LoginUi : AnkoComponent<LoginActivity> {
        override fun createView(ui: AnkoContext<LoginActivity>) = with(ui) {
            verticalLayout {
                backgroundColor = context.resources.getColor(android.R.color.white)
                gravity = Gravity.CENTER_HORIZONTAL
                imageView(R.mipmap.ic_launcher).lparams {
                    width = dip(100)
                    height = dip(100)
                    topMargin = dip(64)
                }

                linearLayout {
                    gravity = Gravity.CENTER_VERTICAL
                    orientation = HORIZONTAL
                    backgroundResource = R.drawable.bg_frame_corner
                    imageView {
                        image = resources.getDrawable(R.mipmap.ic_username)
                    }.lparams(width = wrapContent, height = wrapContent) {
                        leftMargin = dip(12)
                        rightMargin = dip(15)
                    }
                    et_account = editText {
                        hint = "登录账户"
                        hintTextColor = Color.parseColor("#666666")
                        textSize = 16f
                        background = null
                    }
                }.lparams(width = dip(300), height = dip(40)) {
                    topMargin = dip(45)
                }

                linearLayout {
                    orientation = HORIZONTAL
                    backgroundResource = R.drawable.bg_frame_corner
                    gravity = Gravity.CENTER_VERTICAL
                    imageView {
                        image = resources.getDrawable(R.mipmap.ic_password)
                    }.lparams {
                        leftMargin = dip(12)
                        rightMargin = dip(15)
                    }
                    et_password = editText {
                        hint = "登录密码"
                        hintTextColor = Color.parseColor("#666666")
                        textSize = 16f
                        background = null
                    }
                }.lparams {
                    width = dip(300)
                    height = dip(40)
                    topMargin = dip(10)

                }

                button("登录") {
                    gravity = Gravity.CENTER
                    background = resources.getDrawable(R.drawable.bg_login_btn)
                    textColor = Color.parseColor("#ffffff")
                    onClick {
                        if (et_account.text.toString().isNotEmpty() && et_password.text.toString().isNotEmpty())
                            startActivity<MainActivity>() else toast("请输入账户或者密码")
                    }
                }.lparams(width = dip(300), height = dip(44)) {
                    topMargin = dip(18)
                }
                linearLayout {
                    orientation = HORIZONTAL
                    gravity = Gravity.CENTER_VERTICAL
                    checkBox("记住密码") {
                        textColor = Color.parseColor("#666666")
                        textSize = 16f
                        leftPadding = dip(5)
                    }
                    textView("隐私协议") {
                        textColor = Color.parseColor("#1783e3")
                        gravity = Gravity.RIGHT
                        textSize = 16f
                    }.lparams(width = matchParent)
                }.lparams(width = dip(300)) {
                    topMargin = dip(18)
                }

                textView("Copyright © Code4Android") {
                    textSize = 14f
                    gravity = Gravity.CENTER or Gravity.BOTTOM

                }.lparams {
                    bottomMargin = dip(35)
                    weight = 1f
                }
            }
        }
    }

See how the above code looks good, even if you can't write it now, you can read it. Above we set an event to open MainActivity for the login button. The <> of startActivity writes the Activity we want to jump to. If you pass parameters to the open interface, write it directly in (). For example, if we pass the entered account and password to the jump interface, it is implemented as

startActivity<MainActivity>("account" to et_account.text.toString(),"password" to et_password.text.toString())

In fact, the strength of Anko is far more than that, and it is worthy of our careful taste. At this point, this article is over. If you find any mistakes while reading, please point out, thank you, Have a wonderful day. I am your best friend small_world!


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325528081&siteId=291194637