自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Kotlin如何成為我們Android開發(fā)的主要語言

移動(dòng)開發(fā) Android
Kotlin是一個(gè)基于JVM的新的編程語言,由JetBrains開發(fā)。JetBrains,作為目前廣受歡迎的Java IDE IntelliJ的提供商,在Apache許可下已經(jīng)開源其Kotlin編程語言。與Java相比,Kotlin的語法更簡潔、更具表達(dá)性,而且提供了更多的特性,比如,高階函數(shù)、操作符重載、字符串模板。它與Java高度可互操作,可以同時(shí)用在一個(gè)項(xiàng)目中。

Kotlin如何成為我們Android開發(fā)的主要語言

版權(quán)聲明

作者:Dima Kovalenko

譯者:劉志勇

本文由作者授權(quán)翻譯并發(fā)布,未經(jīng)許可不得轉(zhuǎn)載。

原文:https://medium.com/uptech-team/how-kotlin-became-our-primary-language-for-android-3af7fd6a994c#.d16qsda0x

引言

Kotlin是一個(gè)基于JVM的新的編程語言,由JetBrains開發(fā)。JetBrains,作為目前廣受歡迎的Java IDE IntelliJ的提供商,在Apache許可下已經(jīng)開源其Kotlin編程語言。與Java相比,Kotlin的語法更簡潔、更具表達(dá)性,而且提供了更多的特性,比如,高階函數(shù)、操作符重載、字符串模板。它與Java高度可互操作,可以同時(shí)用在一個(gè)項(xiàng)目中。

Kotlin的定位非常有特點(diǎn),它并不像Scala那樣另起爐灶,Scala是一切盡量自己來,將類庫,尤其是集合類都自己來了一遍。實(shí)在不夠用了再用java的;而Kotlin是對現(xiàn)有Java的增強(qiáng),盡量用Java的,不夠用了再擴(kuò)展,尤其體現(xiàn)在二者的容器庫上,但同時(shí)始終保持對java的兼容。這種特點(diǎn)導(dǎo)致Kotlin的學(xué)習(xí)曲線極低。這是Kotlin官網(wǎng)首頁重點(diǎn)強(qiáng)調(diào)的:“100% interoperable with Java™”。這意味著什么呢?或者換個(gè)問法:我什么時(shí)候可以開始在我的項(xiàng)目中引入Kotlin呢?我的回答是:現(xiàn)在就可以視你對kotlin的掌握程度,逐步引入kotlin的代碼。

Dima Kovalenko在博客中分享了他們團(tuán)隊(duì)使用Kotlin開發(fā)商業(yè)應(yīng)用程序的心得和經(jīng)驗(yàn),并提供了一些參考資料。希望本文能對廣大Android開發(fā)程序員有所啟發(fā)。 

幾個(gè)月前,我們的團(tuán)隊(duì)決定開始新的嘗試:完全應(yīng)用Kotlin編程語言開發(fā)一個(gè)商業(yè)應(yīng)用程序,這是JetBrains公司設(shè)計(jì)并開源的一種新編程語言。以前,我們有過Kotlin的經(jīng)驗(yàn),但那只是小規(guī)模應(yīng)用:將應(yīng)用程序的一部分轉(zhuǎn)換到一種新的語言,或者應(yīng)用在花里胡哨的項(xiàng)目。然而,用新的編程語言來開發(fā)商業(yè)應(yīng)用程序,我們遇到了一些困難:

  • 我們深深扎根于基于Java的Android開發(fā)。切換到Kotlin相當(dāng)困難,對于以前沒有函數(shù)式編程經(jīng)驗(yàn)的人員而言,尤為困難。
  • 有些東西只是不工作。 Dagger也沒有立即很好的使用。

所有這些問題,都可能會導(dǎo)致項(xiàng)目無法按期交付、并帶來應(yīng)用程序的穩(wěn)定性問題。

一個(gè)人應(yīng)該有強(qiáng)烈的轉(zhuǎn)型動(dòng)力。我們的激勵(lì)是:相信Kotlin將是Android平臺開發(fā)的顛覆者——并且這是對我們有挑戰(zhàn)的趣事。 

讓我們打開Kotlin的參考書,開始開發(fā)Voter應(yīng)用程序。Kotlin是一種與Java具有100%互操作性的JVM語言,如果您熟悉Java,那么學(xué)習(xí)Kotlin就會很容易。然而,如果想充分利用這個(gè)編程語言,理解函數(shù)式編程概念是至關(guān)重要的。

學(xué)習(xí)函數(shù)式編程需要一段時(shí)間。所以要有耐心。

至少在學(xué)習(xí)之初,函數(shù)式編程并不容易。我強(qiáng)烈建議使用Martin Ordersky的“Scala中的函數(shù)式編程”的課程來學(xué)習(xí)。Scala有時(shí)勢不可擋,但它提供了一個(gè)極好的函數(shù)式編程思維的概述。你可以把Kotlin看成Scala的一個(gè)更簡化的版本。

為什么我們轉(zhuǎn)向Kotlin陣營

函數(shù)式編程風(fēng)格

Kotlin與Java是100%可互操作的。此外,Kotlin是一種函數(shù)式語言。后者允許將表達(dá)性的代碼編寫得更優(yōu)雅。

1. 純函數(shù)

純函數(shù)(沒有副作用的函數(shù))是最重要的函數(shù)概念,它允許我們大大降低代碼復(fù)雜性并消除大多數(shù)可變狀態(tài)。

在JavaScript、Java和C#這些命令式編程語言中,副作用無處不在。這使得調(diào)試非常困難,因?yàn)樽兞靠梢栽诔绦蛑械娜魏挝恢酶摹K援?dāng)出現(xiàn)一個(gè)錯(cuò)誤時(shí),由于變量可以在錯(cuò)誤的時(shí)間更改為錯(cuò)誤的值,那么你到哪里去尋找錯(cuò)誤呢?到處尋找錯(cuò)誤嗎?這可不好玩啊!

請注意我們是如何操作數(shù)據(jù)而不更改其內(nèi)容的。

  1. fun flatTree(tree: TreeNode): List<TreeNode>  
  2. = listOf(tree, *tree.children.flatMap(::flatTree).toTypedArray()) 

2. 高階函數(shù)

高階函數(shù)將函數(shù)用作參數(shù),返回函數(shù)或?qū)⒑瘮?shù)作為返回值的函數(shù)。

高階函數(shù)無處不在。你只需將函數(shù)傳遞給集合,就能使代碼更容易閱讀。比如, titles.map {it.toUpperCase()}讀取簡單的英語,是不是很棒?

讓我們設(shè)想一種情況,假設(shè)要計(jì)算不同類型的未讀消息的數(shù)量。典型的方法是:

  1. private fun getUnreadCountFromUsers() { 
  2.  
  3.     val conversations = datasource.getConversations() 
  4.  
  5.     var count = 0 
  6.  
  7.     for (conversation in conversations) { 
  8.  
  9.       if (conversation.recipientId != null) { 
  10.  
  11.         for (message in conversation.messages) { 
  12.  
  13.           if (message.unread) { 
  14.  
  15.             count += 1 
  16.  
  17.           } 
  18.  
  19.         } 
  20.  
  21.       } 
  22.  
  23.     } 
  24.  
  25.   } 
  26.  
  27.  
  28.   private fun getNumberOfUnreadAttachmentsInGroupConversations() { 
  29.  
  30.     val conversations = datasource.getConversations() 
  31.  
  32.     var count = 0 
  33.  
  34.     for (conversation in conversations) { 
  35.  
  36.       if (conversation.groupId != null) { 
  37.  
  38.         for (message in conversation.messages) { 
  39.  
  40.           if (message.unread && message.type == MessageType.ATTACHMENT) { 
  41.  
  42.             count += 1 
  43.  
  44.           } 
  45.  
  46.         } 
  47.  
  48.       } 
  49.  
  50.     } 
  51.  

正如你所看到的,當(dāng)引入新的需求時(shí),代碼變得難以理解、不可收拾。讓我們看看如何使用高階函數(shù)來解決這個(gè)問題:

  1. private fun getNumberOfAttachmentsInGroupConvesationsFun() { 
  2.  
  3.     return getCount({conv -> conv.groupId != null}, {it -> it.type == MessageType.ATTACHMENT && it.unread}) 
  4.  
  5.   } 
  6.  
  7.  
  8.   private fun getUnreadCountFromUsersFun() { 
  9.  
  10.     return getCount({conv -> conv.recipientId != null}, {message -> message.unread}) 
  11.  
  12.   } 
  13.  
  14.  
  15.   private fun getTotalNumberOfMessages() = getCount({true}, {true}) 
  16.  
  17.  
  18.   private fun getCount(convFilter: (Conversation) -> Boolean, messageFilter: (Message) -> Boolean) { 
  19.  
  20.     datasource.getConversations() 
  21.  
  22.         .filter(convFilter) 
  23.  
  24.         .flatMap { it.messages } 
  25.  
  26.         .filter(messageFilter) 
  27.  
  28.         .fold(0, { count, message -> count + 1}) 
  29.  

我們還可以想象一下用例,假設(shè)想將fold函數(shù)變量參數(shù)化。比方說,計(jì)算未讀消息的乘積。

使用高階函數(shù)的另一個(gè)例子是用簡單的高階函數(shù)代替多個(gè)監(jiān)聽器:

  1. BillingView : LinearLayout { 
  2.   var billingChangeListener: (() -> Unit)? = null 
  3.   ... 
  4. ... // in an activity far, far away 
  5. billingView.billingChangeListener { updateUI() } 

3. 不變性

不變性使得代碼更容易編寫,使用和推理代碼(類不變性一次建立,然后不變——一勞永逸)。應(yīng)用程序組件的內(nèi)部狀態(tài)將更加一致。Kotlin通過引入val關(guān)鍵字以及Kotlin集合來強(qiáng)制不變性,Kotlin集合在默認(rèn)情況下是不可變的。 一旦val或者一個(gè)集合被初始化,你就可以確定它的有效性。(有關(guān)val關(guān)鍵字的更精確的定義,請參閱文末的更新)。

  1. data class Address(val line1: String, val city: String) 
  2. val items = listOf(Address("242 5th St""Los Angeles"),   Address("Dovzhenka St. 5""Kiev")) 

Null-safety

這個(gè)語言特性使我們仔細(xì)考慮了模型類中字段的可空性。以前,當(dāng)不確定DTO中的字段是否已初始化時(shí),@Nullable和@NotNull的注釋就能提供幫助,但也很有限?,F(xiàn)在,使用Kotlin,就能讓你準(zhǔn)確知道什么字段可以為null,什么字段被初始化(例如,Dagger注入的字段),并且你可以對這些字段有嚴(yán)格的控制。結(jié)果?幾乎沒有NullPointerExceptions。(在內(nèi)部我們管?.叫做“鵝”操作符,因?yàn)樗雌饋硐褚粋€(gè)鵝的脖子。)

  1. brand?.let { badge.enabled = brand.isNewBadge } 
  2. // Can also be written as  
  3. badge.enabled = brand?.isNewBadge?:false 

Anko

Anko DSL是一個(gè)很了不起的的庫,它大大簡化了工作視圖、線程和Android生命周期。據(jù)Github的描述,Anko是“令人愉快的Android應(yīng)用程序開發(fā)”,事實(shí)證明,的確如此。

  1. selector(items = listOf("Like""Dislike") { 
  2.  
  3.     when (it) { 
  4.  
  5.       0 -> if (!liked) likePost() 
  6.  
  7.       else -> if (!disLiked) disLikePost() 
  8.  
  9.     } 
  10.  
  11.  
  12.  
  13. doAsync { 
  14.  
  15.     // Long background task 
  16.  
  17.     uiThread { 
  18.  
  19.       alert(R.string.could_not_log_in) { 
  20.  
  21.         yesButton { dismiss() } 
  22.  
  23.         cancellable = false 
  24.  
  25.       }.show() 
  26.  
  27.     } 
  28.  

注意,當(dāng)uiThread在Activity內(nèi)調(diào)用時(shí),如果isFinishing為true,塊將不會執(zhí)行。我們實(shí)際上不使用這個(gè)功能,因?yàn)镽xJava會處理應(yīng)用程序中的所有線程,但它是一個(gè)很好的功能。

使用Anko而不是XML。雖然Anko還沒有做好準(zhǔn)備取代標(biāo)準(zhǔn)的Android UI構(gòu)建,但有的時(shí)候,它非常方便。

  1. verticalLayout() { 
  2.  
  3.  
  4.   friendsPanel = friendsPanel.with(friendsData).lparams(width = matchParent) 
  5.  
  6.  
  7.   politicalMapCardView { 
  8.  
  9.     setMarker(quizManager.getMarker()) 
  10.  
  11.   }.lparams(width = matchParent) { topMargin = dip(10) } 
  12.  
  13.  
  14.   cardView() { 
  15.  
  16.     verticalLayout() { 
  17.  
  18.       topPadding = dip(5) 
  19.  
  20.       textView(getString(R.string.register_question)) 
  21.  
  22.       blueButtonView(text="Register here") { 
  23.  
  24.         onClick { browse("https://www.uptech.team") } 
  25.  
  26.       } 
  27.  
  28.     } 
  29.  
  30.   }.lparams(width = matchParent) { 
  31.  
  32.     topMargin = dip(10) 
  33.  
  34.     bottomMargin = dip(20) 
  35.  
  36.   } 
  37.  

如您所見,Anko DSL允許您在Android內(nèi)置視圖中使用自定義視圖。這一點(diǎn)與標(biāo)準(zhǔn)XML相比有很大的優(yōu)勢。

Kotlin Android擴(kuò)展:刪除ButterKnife依賴

  1. @Bind(R.id.first_name) 
  2.  
  3.     protected EditText firstName; 
  4.  
  5.  
  6.     @Bind(R.id.last_name) 
  7.  
  8.     protected EditText lastName; 
  9.  
  10.  
  11.     @Bind(R.id.address_line1) 
  12.  
  13.     protected EditText addressLine1; 
  14.  
  15.  
  16.     @Bind(R.id.address_line2) 
  17.  
  18.     protected EditText addressLine2; 
  19.  
  20.  
  21.     @Bind(R.id.zip_code) 
  22.  
  23.     protected EditText zipCode; 
  24.  
  25.  
  26.     @Bind(R.id.state) 
  27.  
  28.     protected TextView state; 
  29.  
  30.  
  31.     @Bind(R.id.state_spinner) 
  32.  
  33.     protected HintSpinner stateSpinner; 
  34.  
  35.  
  36.     @Bind(R.id.city) 
  37.  
  38.     protected EditText city; 
  39.  
  40.  
  41.     @Bind(R.id.frag_shipping_address_save_btn) 
  42.  
  43.     protected Button saveBtn; 
  44.  
  45.  
  46.     @Bind(R.id.agreement) 
  47.  
  48.     protected TextView agreement; 
  49.  
  50.  
  51.     @Bind(R.id.email) 
  52.  
  53.     protected EditText email; 
  54.  
  55.  
  56.     @Bind(R.id.password
  57.  
  58.     protected EditText password
  59.  
  60.  
  61.     @Bind(R.id.create_account_container) 
  62.  
  63.     protected LinearLayout accountContainer; 
  64.  
  65.  
  66.     @Bind(R.id.member_container) 
  67.  
  68.     protected LinearLayout memberContainer; 
  69.  
  70.  
  71.     @Bind(R.id.logged_in_title) 
  72.  
  73.     protected TextView loggedInTitle; 
  74.  
  75.  
  76.     @Bind(R.id.user_email) 
  77.  
  78.     protected TextView userEmail; 
  79.  
  80.  
  81.     @Bind(R.id.sign_out) 
  82.  
  83.     protected TextView signOut; 
  84.  
  85.  
  86.     @Bind(R.id.scrollview) 
  87.  
  88.     protected ScrollView scrollView; 
  89.  
  90.  
  91.     @Bind(R.id.dummy) 
  92.  
  93. protected EditText dummyView; 

上面那段代碼讀起來無聊嗎?我敢打賭你一直滾動(dòng)而沒有閱讀。在Kotlin,你并不需要任何這些東西。您可以通過其@id XML參數(shù)引用視圖屬性,這些屬性將與XML文件中聲明的名稱相同。更多信息可以在官方文檔中找到。

其他整潔的功能

1. 擴(kuò)展功能和構(gòu)建器

  1. items = StoreInfo().apply { storeItems = fetchItems() }.let { manager.process(it) } 
  2.  
  3. container.apply { 
  4.  
  5.   removeAllViews() 
  6.  
  7.   items.forEach { addView(ShopItemView(context).withData(it)) } 
  8.  
  9.  
  10.  
  11. fun ShopItemView.withData(item: StoreItem): ShopItemView { 
  12.  
  13.   title = item.title 
  14.  
  15.   image = item.image 
  16.  
  17.   Brand.findById(item.id)?.let { brandName = it.name } 
  18.  

apply、let和擴(kuò)展功能可以輕松地用于創(chuàng)建簡潔的構(gòu)建器。

2. 為初學(xué)者快速破解

在最初的前幾天,你經(jīng)常被一個(gè)問題難倒:你不知道如何在Kotlin中寫一個(gè)相當(dāng)簡單的Java表達(dá)式。這里有一個(gè)簡單的訣竅,就是是在Java中編寫一段代碼,然后將其粘貼到Kotlin文件中。感謝JetBrains的工程師們,它會自動(dòng)轉(zhuǎn)換為Kotlin。

黑客的工作方式就像一個(gè)魔術(shù)!

3. 擺脫不必要的依賴

Kotlin替換了許多第三方庫,如ButterKnife、Google Autovalue、Retrolambda、Lombok和一些RxJava代碼。

總結(jié)

作為一個(gè)軟件開發(fā)團(tuán)隊(duì),我們面臨的主要挑戰(zhàn)是提供優(yōu)秀的產(chǎn)品,并有效地完成工作。雖說開始用Kotlin有效的開發(fā)軟件,需要你有函數(shù)式編程的背景,但是,投入精力去學(xué)習(xí)是值得的,能給你巨大的回報(bào)。我相信,Kotlin是常規(guī)Android開發(fā)的一個(gè)重大改進(jìn),能讓我們及時(shí)提供錯(cuò)誤更少的、更加優(yōu)秀的應(yīng)用程序。

更新:val實(shí)際上并不意味著“不可變的”,而是“只讀”。有關(guān)詳細(xì)信息,請參閱下面的參考文章。

參考文獻(xiàn)

《Kotlin 參考手冊》 https://kotlinlang.org/docs/reference/

《所以,你要成為一名函數(shù)式程序員》 https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-1-1f15e387e536#.8cmkitum2

《為什么函數(shù)式編程很重要》 https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf

《Java使用不可變對象編程的6大好處》 https://www.linkedin.com/pulse/20140528113353-16837833-6-benefits-of-programming-with-immutable-objects-in-java

《Anko DSL對Android XML-First》 http://maximomussini.com/posts/anko-vs-android-xml/

《將應(yīng)用轉(zhuǎn)換為純Kotlin的經(jīng)驗(yàn)教訓(xùn)》 https://medium.com/keepsafe-engineering/lessons-from-converting-an-app-to-100-kotlin-68984a05dcb6#.jkxs39qko

《結(jié)果:應(yīng)用程序投票選舉:99.8%無故障用戶》 https://play.google.com/store/apps/details?id=app.voter.xyz&hl=en

《Kotlin:val不意味著不可變,而意味著只讀》 https://artemzin.com/blog/kotlin-val-does-not-mean-immutable-it-just-means-readonly-yeah/

責(zé)任編輯:龐桂玉 來源: 移動(dòng)開發(fā)前線
相關(guān)推薦

2017-02-28 09:02:10

科技早新聞

2024-01-08 09:00:00

開發(fā)DSLKotlin

2011-11-07 15:05:54

程序語言StackOverflObjective-C

2018-04-22 00:01:43

JavaScript Node 語言

2009-01-15 13:26:14

PHPWeb開發(fā)ASP.NET

2017-12-09 22:09:05

編程KotlinC語言

2017-05-22 11:09:53

KotlinAndroid

2018-02-08 10:52:13

Kotlin語言代碼

2022-06-23 09:22:57

Vue技巧前端

2023-09-15 14:29:57

Android開發(fā)語言

2019-04-16 09:00:05

AndroidKotlinJava

2018-04-24 15:00:59

Kotlin語言函數(shù)

2017-12-27 14:51:12

Kotlin谷歌Java

2009-04-07 08:45:52

GPONFTTx

2011-12-27 09:31:13

程序員

2021-12-10 23:48:19

Java開發(fā)技術(shù)

2014-02-26 11:18:02

Android開發(fā)偷懶高效

2020-09-02 14:08:04

Kotlin語言開發(fā)者

2020-07-04 11:01:36

Kotlin開發(fā)Android

2014-04-29 10:44:50

驅(qū)動(dòng)開發(fā)開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號