最近Kotlin的呼聲又是日益高漲,前幾天9012年Google IO正式將Kotlin從first _class提高爲kotlin_first。我也是接觸了一段時間的Kotlin,給個人感受就是簡約,快速。無需繁瑣的findId,高階函數的應用,再加上Kotlin的null 安全,更是將代碼的崩潰率降到更低。html
今天咱們就來介紹一下今天的主角---Ankojava
Anko是JetBrains開發的一個強大的庫,提及JetBrains ,那就牛逼了,Kotlin語言是他們開發的,最流行的的開發工具intellij idea都是他們開發的,AS也是基於IDEA的。好了,言歸正傳,Anko是Kotlin官方開發的一個讓開發Android應用更快速更簡單的Kotlin庫,而且能讓咱們書寫的代碼更簡單清楚更容易閱讀。它包括多個部分react
添加依賴android
dependencies {
implementation "org.jetbrains.anko:anko:$anko_version"
}
複製代碼
這裏麪包括上面四個部分,固然你也能夠只依賴一個部分,以下:sql
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"
}
複製代碼
下面咱們分別介紹這幾個功能。數據庫
AnkoCommons對Android開發者來講是一個工具集,包括但不限於下面這幾個數組
前面已經提到,Commons 庫是一個工具集,那Intents主要是幫助簡化Activity之間的跳轉。安全
傳統的 Kotlin 啓動新的 Activity 的方式是建立一個 Intent,同時可能傳遞一些參數,最後將建立的 Intent 經過 Context 的 startActivity() 方法傳遞,就像這樣:bash
val intent = Intent(this, SomeOtherActivity::class.java)
intent.putExtra("id", 5)
intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
複製代碼
然鵝你用Anko只須要這樣:app
startActivity(intentFor("id" to 5).singleTop())
若是想要傳遞多個參數,你也能夠這樣
startActivity<SomeOtherActivity>(
"id" to 5,
"city" to "Denpasar"
)
複製代碼
固然還有一些關於Intent的其它操做,如:撥打電話等:以下
這個庫主要是用來快速搭建Dialog和toast,具體包含如下幾個
Anko爲咱們提供了更加簡單的Toast使用,只須要一行代碼便可實現
toast("Hi there!")
toast(R.string.message)
longToast("Wow, such duration")
複製代碼
SnackBar是 Android Support Library 22.2.0 裏面新增提供的一個控件,咱們能夠簡單的把它理解成一個增強版的Toast,或者是一個輕量級的Dialog。 咱們能夠用下面代碼快速建立snackbar。
view.snackbar("Hi there!")
view.snackbar(R.string.message)
view.longSnackbar("Wow, such duration")
view.snackbar("Action, reaction", "Click me!") { doStuff() }
複製代碼
這裏須要傳入view對象,這個能夠是佈局中的任意一個view對象。
Anko Alerts主要包括如下幾個功能:
1.Android 默認dialog 經過如下代碼就能夠構建一個能夠交互的Android 默認dialog。
alert("Hi, I'm Roy", "Have you tried turning it off and on again?") {
yesButton { toast("Oh…") }
noButton {}
}.show()
複製代碼
代碼比較簡單,就不作解釋。
2.Android Appcompat 中AlertDialog 另外Anko還提供了Appcompat的AlertDialog實現方式,以下:
alert(Appcompat, "Some text message").show()
複製代碼
3.自定義Dialog 什麼,不能自定義dialog嗎?怎麼會,自定義dialog也是很是的簡單
alert {
customView {
editText()
}
}.show()
複製代碼
2.2.4 Selectors (包含列表的Dialog)
咱們平時建立列表Dialog是這樣的:
val listItems = arrayOf("Russia", "USA", "Japan", "Australia") //傳數組
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 = params
複製代碼
可是咱們用Anko是這樣的:
val countries = listOf("Russia", "USA", "Japan", "Australia") //傳list
selector("Where are you from?", countries, { dialogInterface, i ->
toast("So you're living in ${countries[i]}, right?")
})
複製代碼
看起來只是簡化了dialog的建立過程。
不顯示進度的 Loading Dialg
pressDialog("Please wait a minute.", "Downloading…")
indeterminateProgressDialog("Fetching the data…")
複製代碼
打印log輔助工具。
Android SDK 提供 android.util.Log 類來提供一些 logging 方法,,這些方法都很實用,可是咱們每次必須傳遞一個 Tag 參數,同時這個 Tag 信息必須是 String 類型的,這就略顯麻煩。不過如今咱們能夠經過 AnkoLogger 類擺脫這些惱人的問題:
class SomeActivity : Activity(), AnkoLogger {
fun someMethod() {
info("Info message")
debug(42) // .toString() method will be called automatically
}
}
複製代碼
默認的 Tag 名是當前的類名( 本例中的是SomeActivity),可是經過重寫 AnkoLogger 的 loggerTag 屬性咱們是能夠來更改的,並且每一個方法有兩個版本:plain and lazy (inlined)
1.Lazy:
info("String " + "concatenation")
info { "String " + "concatenation" }
複製代碼
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!")
}
}
複製代碼
上面兩種方法分別是不一樣Tag的實現方式。
你能夠在你的項目中使用Anko Resources and dimensions來簡化你的代碼,例如Color、Dimen等,顏色透明度直接色值.opaque就能夠,尺寸的話直接使用dip(dipValue)、sp(spValue)就能夠。在這裏面還有一個就是applyRecursively()用來控制子View的操做,如:
verticalLayout {
textView{
text = "EditText01"
backgroundColor = 0xff000.opaque
textSize = 14f
}
textView {
text = "EditText02"
backgroundColor = 0x99.gray.opaque
textSize = 23f
}
}.applyRecursively {//若是是ViewGroup的話可使用applyRecursively來爲每一個Child View進行設置
view -> when(view){
is TextView -> view.textColor = Color.RED
}
}
複製代碼
一般咱們使用xml文件寫咱們的佈局,可是他有一些缺點如不是類型安全,不是空安全,解析xml文件消耗更多的CPU和電量等等。而Anko Layout可使用DSL(Domain Specific Language)動態建立咱們的UI,而且它比咱們使用Java動態建立佈局方便不少主要是更簡潔,它和擁有xml建立佈局的層級關係,能讓咱們更容易閱讀。(官方說的優勢)
舉個栗子:
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
複製代碼
上面的代碼是否是很簡單易懂,固然,默認的控件並不能知足咱們的需求,例如咱們會更改字體的顏色及大小,會設置寬度和高度,會設置margin,padding值,那麼該如何實行呢,固然也很簡單,由於它的邏輯和xml書寫佈局是一個套路。例如如下實現
val textView=textView("我是一個TextView"){
textSize = sp(17).toFloat()
textColor=0xff000.opaque
}.lparams{
margin=dip(10)
height= dip(40)
width= matchParent
}
複製代碼
配合上前面Common庫是否是很簡單呢?
這裏咱們不須要setContentView。直接寫在onCreate方法中就行。
在上面建立UI過程當中,咱們直接把建立UI的代碼寫在onCreate方法中了,固然,還有一種寫法。咱們建立一個內部類實行AnkoComponent接口,並重寫createView方法,該方法返回一個View,也就是咱們建立的佈局。修改以下
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}!") }
}
}
}
}
複製代碼
如今咱們編譯運行,發現效果和佈局文件寫的界面是同樣的。可是它的性能是有優點的,其實吧並無發覺性能優點。無論怎樣,這種DSL確實便於閱讀,也很容易上手,在上面的代碼中,你可能注意到了dip(10),它表示將10dp轉換爲像素的意思,是Anko的擴展函數,說的擴展函數,若是閱讀過Anko的源碼咱們發現裏面大量的使用擴展函數,這也是Kotlin語言的優點之一。
這裏就簡單介紹下Layout的使用和優勢。可是我想各位看官在實際開發中也不必定會用,由於不可視化用起來實在難以接受。不過這種見仁見智吧。
Anko SQLite是一個查詢解析SQLite的領域專用語言
SQLite 存在的不足:
隨着你應用的數據庫愈來愈複雜,暴露出來的問題也會越多。因此也難怪不少人會選擇 ORM 或者 NoSQL,但這帶來的方便性是以增長應用大小和方法數爲代價的。
若是你打算使用 Kotlin 來開發 Android 應用,那麼如今經過 Anko SQLite 就能夠很方便的進行 SQLite 操做了。好比能夠告別麻煩的 Cursor 和 ContentValue、內置安全機制,保證數據庫在執行全部代碼後可以關閉。
經過繼承 ManagedSQLiteOpenHelper 類來實現數據庫幫助類,推薦作法就是按照官方的實現:
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)
}
}
複製代碼
訪問數據庫的推薦作法是經過依賴注入,或者爲 Context 添加一個 extension:
val Context.database: DatabaseHelper
get() = DatabaseHelper.Instance(applicationContext)
複製代碼
下面這是一個簡單的 model 類:
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"
}
}
複製代碼
當數據庫準備好後,就能夠經過 use 方法來進行操做了。好比:
database.use {
insert(Book.TABLE_NAME, Book.COLUMN_ID to 1, Book.COLUMN_TITLE to "2666", Book.COLUMN_AUTHOR to "Roberto Bolano")
}
複製代碼
最後,讓咱們來比較一下常見庫的大小:
要注意這裏 Anko SQLite 的依賴大小實際上是包含了 Kotlin Runtim (method count: 6298, DEX size: 1117 KB) 和 Anko Commons module (method count: 982, DEX size: 174 KB) 的。所以若是你是經過 Kotlin 來開發,Anko SQLite 增長的大小其實並無圖表顯示得那麼多。
所以,若是你在使用 Kotlin 作開發而且數據庫的複雜度不高,首推 Anko SQLite。但若是數據庫結構很是複雜,DAO 和 SQL 查詢可能會變得很痛苦,這時候 ORM 和 NoSQL 就是首選方案了。
Kotlin協程 協程本質上是一個輕量級的線程,支持咱們用同步寫法寫異步請求,而不用Callback。
doAsync(UI) {
val data: Deferred<Data> = bg {
// Runs in background
getData()
}
// This code is executed on the UI thread
showData(data.await())
}
複製代碼
咱們能夠用bg()在新的線程去作耗時操做,等返回結果再在UI線程進行操做。
具體協程教程咱們能夠看一下官方文檔
Anko是Kotlin官方開發的一個讓開發Android應用更快速更簡單的Kotlin庫,而且能讓咱們書寫的代碼更簡單清楚更容易閱讀。 主要包含了如下幾個部分。
Anko庫用起來很是的簡單方便,裏面設計到DSL和擴展函數。
關於DSL能夠看下這篇文章
關於擴展函數能夠看下這篇文章