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

一覺醒來Kotlin成了Android的新寵兒【附代碼】

移動開發(fā) Android
開始做安卓UI開發(fā)一直是使用XML文件來實(shí)現(xiàn)。雖然理論上,UI可以使用Java語言來實(shí)現(xiàn),但并沒有太多的用處。不久前,JetBrains推出了Kotlin,一種面向JVM的現(xiàn)代語言,可以很好的實(shí)現(xiàn)安卓UI。

前言

凌晨的谷歌I/O 2017開發(fā)者大會直播你有沒有觀看呢?安卓雖然已經(jīng)成為了移動設(shè)備***操作系統(tǒng),全球采用Android操作系統(tǒng)的激活設(shè)備超過了20億臺。不過對于谷歌來說,需要依靠java來做安卓開發(fā)一直是一個(gè)心病,因?yàn)閛racle公司因?yàn)閖ava和谷歌在安卓系統(tǒng)上的訴訟搞得心力憔悴。

現(xiàn)在好了,谷歌官方正式支持Kotlin,成為官方認(rèn)可的安卓開發(fā)***語言,而且從Android Studio 3.0開始,將直接集成Kotlin而無需安裝任何的插件。

正文

開始做安卓UI開發(fā)一直是使用XML文件來實(shí)現(xiàn)。雖然理論上,UI可以使用Java語言來實(shí)現(xiàn),但并沒有太多的用處。不久前,JetBrains推出了Kotlin,一種面向JVM的現(xiàn)代語言,可以很好的實(shí)現(xiàn)安卓UI。

Jetbrains宣稱Anko是Android中更快,更輕松的開發(fā)風(fēng)格。Kotlin提供Anko庫來作為DSL(領(lǐng)域?qū)S谜Z言)去設(shè)計(jì)安卓界面,一個(gè)簡單的例子:

下面的界面由一個(gè)圖片和一個(gè)按鈕組成:

 

使用Anko實(shí)現(xiàn)如下:

  1. verticalLayout{ 
  2.        imageView(R.drawable.anko_logo). 
  3.                 lparams(width= matchParent) { 
  4.                     padding = dip(20) 
  5.                     margin = dip(15) 
  6.         } 
  7.         button("Tap to Like") { 
  8.                 onClick { toast("Thanks for the love!") } 
  9.         } 
  10.     }  

我們定義了一個(gè)垂直的線性布局作為容器包含圖片和按鈕,使用lparams定義了布局的位置信息,由Kotlin的內(nèi)聯(lián)函數(shù)也實(shí)現(xiàn)了按鈕的點(diǎn)擊事件。

使用Anko的優(yōu)點(diǎn):

  • 我們可以將UI布局嵌入到代碼中,從而使其類型安全。
  • 由于我們不用XML編寫,所以它增加了效率,因?yàn)樵诜治鯴ML浪費(fèi)CPU時(shí)間。
  • 在UI的程序化轉(zhuǎn)換之后,我們可以將Anko DSL片段放入一個(gè)函數(shù)中。這樣便于代碼重用。
  • 顯然,代碼更簡潔,可讀和可掌握性更高。

現(xiàn)在我們使用Anko Layout和Kotlin構(gòu)建一個(gè)to-do app,來列出我們今天需要做的事。

你可以在GitHub上找到這個(gè)項(xiàng)目 to-do app

將Anko庫添加到Android Studio:

在streamline-android-java-code-with-kotlin去學(xué)習(xí)如何添加Kotlin到你的安卓項(xiàng)目中,有了Kotlin,我們需要添加Anko依賴在app/build.gradle中,這樣我們就可以順利編譯項(xiàng)目了。

  1. compile [size=1em]'org.jetbrains.anko:anko-sdk15:0.8.3' 
  2.  
  3. // sdk19,21,23 也可以使用 

可以根據(jù)你項(xiàng)目的minSdkVersion來添加這個(gè)依賴,上面的例子說明15<=minSdkVersion<19,你可以在Anko的GitHub庫中找到自己需要的其他Anko依賴庫。

我們準(zhǔn)備使用下面的依賴庫:

  1. compile 'org.jetbrains.anko:anko-design:0.8.3' 
  2.  
  3. compile 'org.jetbrains.anko:anko-appcompat-v7:0.8.3' 

在Activity中調(diào)用Anko布局:

我們不再使用XML來寫布局文件,所以我們不需要XML View,所以也不需要findViewById()方法了。這里我們假設(shè)我們的Anko布局類為MainUI,然后我們可以開始寫我們的activit內(nèi)容:

  1. var ui =MainUI()           //MainUI類代替了XML布局 
  2.  
  3. ui.setContentView(this)   //this代表Activity類 

現(xiàn)在我們創(chuàng)建一個(gè)Kotlin文件MainActivity.kt,寫上如下代碼:

  1. class MainActivity : AppCompatActivity() {    val task_list = ArrayList<String>()         //任務(wù)清單表 
  2.     override fun onCreate(savedInstanceState: Bundle?) { 
  3.        super.onCreate(savedInstanceState) 
  4.        savedInstanceState?.let {           val arrayList = savedInstanceState.get("ToDoList"
  5.            task_list.addAll(arrayList as List<String>) 
  6.        }       var adapter=TodoAdapter(task_list)      //定義適配器 
  7.        var ui = MainUI(adapter)                //定義將要使用的Anko UI 布局 
  8.        ui.setContentView(this)                 //給Activity設(shè)置Anko布局 
  9.    }   override fun onSaveInstanceState(outState: Bundle?) { 
  10.        outState?.putStringArrayList("ToDoList", task_list) 
  11.        super.onSaveInstanceState(outState) 
  12.      } 
  13.  }  

task_list是ArrayList,將填充ListView的TodoAdapter。MainUI(adapter)是我們的Anko UI文件,它采用TodoAdapter類作為適配器參數(shù)。所以,接下來我們再創(chuàng)建一個(gè)TodoAdapter類。

用于ListView的TodoAdapter適配器

TodoAdapter類有一個(gè)ArrayList<String>類型的list,并且繼承了BaseAdapter。所以我們需要重寫一下四個(gè)方法:

public int getCount()public Object getItem(int i)public long getItemId(int i)public View getView(int i, View view, ViewGroup viewGroup)

在getView()方法中我們需要使用Anko設(shè)計(jì)一個(gè)表元素的布局。

  1. public int getCount()public Object getItem(int i)public long getItemId(int i)public View getView(int i, View view, ViewGroup viewGroup) 
  2.  
  3.         在getView()方法中我們需要使用Anko設(shè)計(jì)一個(gè)表元素的布局。 
  4.  
  5. override fun getView(i : Int, v : View?, parent : ViewGroup?) : View { 
  6.               return with(parent!!.context) {              //任務(wù)數(shù)從1開始 
  7.               var taskNum: Int = i +1 
  8.              //清單表元素布局 
  9.              linearLayout { 
  10.                    lparams(width = matchParent, height = wrapContent) 
  11.                    padding = dip(10) 
  12.                    orientation = HORIZONTAL                   //任務(wù)號 
  13.                   textView { 
  14.                        id = R.id.taskNum 
  15.                        text=""+taskNum 
  16.                        textSize = 16f 
  17.                        typeface = Typeface.MONOSPACE 
  18.                        padding =dip(5) 
  19.                   }                  //任務(wù)名 
  20.                   textView { 
  21.                         id = R.id.taskName 
  22.                        text=list.get(i) 
  23.                        textSize = 16f 
  24.                        typeface = DEFAULT_BOLD 
  25.                        padding =dip(5) 
  26.                   } 
  27.              } 
  28.          } 
  29.       } 
  • 在這個(gè)方法中,我們返回一個(gè)包含一個(gè)horizontalListView布局列表項(xiàng)的視圖。這是使用Kotlin的with語法完成的,它允許我們一次在對象實(shí)例上調(diào)用很多方法。
  • 每個(gè)列表項(xiàng)包含兩個(gè)textview用于顯示任務(wù)號和任務(wù)名稱。
  • linearLayout,textView是擴(kuò)展功能。擴(kuò)展功能使我們有能力啟用具有新功能的任何類。
  • text,textSize,typeface在android.widget.TextView有g(shù)etter和setter方法,padding是Anko添加的屬性。

繼續(xù)下一步,我們需要定義列表的操作功能。因此,我們需要在TodoAdapter中定義add(String)和delete(Int)方法。add(String)將任務(wù)名稱作為參數(shù)添加到任務(wù)中。delete(Int)將任務(wù)所在的位置作為參數(shù)來刪除任務(wù)。下面是具體的實(shí)現(xiàn):

  1. //將任務(wù)添加到任務(wù)清單的方法      
  2.  fun add(text: String) {          
  3.        list.add(list.size, text)          
  4.        notifyDataSetChanged()          //更新數(shù)據(jù)    }       //將任務(wù)從任務(wù)清單中移除的方法      
  5.  fun delete(i:Int) {         
  6.        list.removeAt(i)          
  7.        notifyDataSetChanged()          //更新數(shù)據(jù)      
  8.  }  

所以,現(xiàn)在我們設(shè)計(jì)了列表,我們也可以添加和刪除項(xiàng)目到我們的列表中。接下來完成此適配器類的代碼。

  1.  TodoAdapter(val list: ArrayList<String> = ArrayList<String>()) : BaseAdapter() {     
  2.                override fun getView(i : Int, v : View?, parent : ViewGroup?) : View {         
  3.                          return with(parent!!.context) {             
  4.                                    //taskNum will serve as the S.Noof the list starting from 1             
  5.                                    var taskNum: Int = i +1            
  6.                                    //Layout for a list view item             
  7.                                    linearLayout {                 
  8.                                           id = R.id.listItemContainer                 
  9.                                           lparams(width = matchParent, height = wrapContent)                 
  10.                                           padding = dip(10)                 
  11.                                           orientation = HORIZONTAL                 
  12.                                              textView {                     
  13.                                                    id = R.id.taskNum                    
  14.                                                    text=""+taskNum                    
  15.                                                    textSize = 16f                   
  16.                                                    typeface = Typeface.MONOSPACE                 
  17.                                                    padding =dip(5)                
  18.                                              }                 
  19.                                           textView {                    
  20.                                                   id = R.id.taskName                    
  21.                                                   text=list.get(i)                    
  22.                                                   textSize = 16f                     
  23.                                                   typeface = DEFAULT_BOLD                    
  24.                                                   padding =dip(5)                
  25.                                            }            
  26.                                     }         
  27.                                 }    
  28.                            }    
  29.            override fun getItem(position : Int) : String {         
  30.                       return list[position     
  31.             }     
  32.            override fun getCount() : Int {        
  33.                       return list.size    
  34.             }     
  35.            override fun getItemId(position : Int) : Long {         
  36.                      //can be used to return the item's ID column of table         
  37.                      eturn 0L     
  38.             }     
  39.            //function to add an item to the list     
  40.            fun add(text: String) {              
  41.                    list.add(list.size, text)         
  42.                    notifyDataSetChanged()    
  43.            }     
  44.           //function to delete an item from list    
  45.           fun delete(i:Int) {         
  46.                    list.removeAt(i)         
  47.                    notifyDataSetChanged()    
  48.           } 
  49.  

注意,使用Anko DSL類中必須要導(dǎo)入org.jetbrains.anko.*。

設(shè)計(jì)項(xiàng)目的外觀

Anko為我們提供了在單獨(dú)的Kotlin類中為Activity使用UI的便利。因此,每個(gè)屏幕都可以被認(rèn)為是Kotlin類的UI-Activity匹配對。這個(gè)UI類是通過繼承在org.jetbrains.anko包中定義的AnkoComponent<T>接口的功能來實(shí)現(xiàn)的。

除了這個(gè)接口,JetBrains還提供免費(fèi)的DSL布局預(yù)覽功能。下面是Anko DSL布局預(yù)覽在Android Studio中的樣子:

 

Anko Preview的相應(yīng)插件可以從這里下載。請注意,在撰寫本文時(shí),Android Studio 2.2的Anko DSL 布局預(yù)覽被列為開源issue。

回到正題,我們接下來設(shè)計(jì)MainUI類展示所有任務(wù)列表。MainUI類繼承了AnkoComponent<T>接口,其中T指的是UI的所有者,activity的內(nèi)容將會是這個(gè)UI。在我們的例子中,所有者就是我們已經(jīng)在上面定義的MainActivity。接下來,在初始化時(shí),我們必須將TodAadapter對象傳遞給此類,因?yàn)榇诉m配器將用于填充列表。所以,MainUI聲明變成:

  1. class MainUI(val todoAdapter : TodoAdapter) : AnkoComponent<MainActivity> 

現(xiàn)在我們需要重寫方法 createView() ,使用 AnkoContext 對象作為參數(shù)并返回一個(gè)View 類型:

  1. override fun createView(ui: AnkoContext<MainActivity>): View = with(ui) { 
  2.  
  3. } 

我們在createView() 方法中UI定義返回給所有者即activity,在這里也就是MainActivity,所以接下來寫createView() 方法:

Step1-設(shè)計(jì)首頁

 

最初,首頁是空列表。所以,我們有一個(gè)textView要求用戶創(chuàng)建一天的Todo List:

  1. return relativeLayout {         
  2.                          //聲明ListView         
  3.                         var todoList : ListView? =null        
  4.                         //當(dāng)沒有任務(wù)時(shí)顯示textView內(nèi)容"What's your Todo List for today?"         
  5.                         val hintListView = textView("What's your Todo List for today?") {             
  6.                                             textSize = 20f       
  7.                           }.lparams {             
  8.                     centerInParent()         
  9.                    } 
  10.        }  

centerInParent() 是將視圖的布局定義為垂直和水平相對中心的輔助方法。因?yàn)樗且粋€(gè)todo性質(zhì)的應(yīng)用,其本質(zhì)在于顯示任務(wù)的列表。所以,我們在這里定義listView:

  1. //listView   
  2.   verticalLayout {                 
  3.                todoList=listView {                 
  4.               //assign adapter                 
  5.              adapter = todoAdapter               
  6.               }            
  7.       }.lparams {                 
  8.           margin = dip(5)            

todoAdapter是我們在MainUI類聲明中定義成員變量。我們用todoAdapter的值初始化listView的adapter,這是一個(gè)TodoAdpater類的對象,將會用于填充列表。

為了幫助用戶添加任務(wù),我們在主屏幕的右下方提供了一個(gè)Material design風(fēng)格的floatingActionButton。所以我們使用Anko編程floatingActionButton為:

  1. floatingActionButton {                           
  2.          imageResource = android.R.drawable.ic_input_add         
  3.           }.lparams {             
  4.                           //設(shè)置按鈕在屏幕的右下方             
  5.                            margin = dip(10)             
  6.                            alignParentBottom()             
  7.                            alignParentEnd()             
  8.                            alignParentRight()             
  9.                            gravity = Gravity.BOTTOM or Gravity.END        
  10.     }  

篇幅所限,Step2、Step3請點(diǎn)擊左下角“閱讀原文”查看全部文章。

***的想法

我們在開發(fā)此to-do app時(shí)沒有使用任何XML布局資源,但我們能夠以類似的風(fēng)格設(shè)計(jì)應(yīng)用程序。Anko從應(yīng)用程序的activity或fragments中消除了呈現(xiàn)數(shù)據(jù)的負(fù)擔(dān),響應(yīng)用戶交互,連接數(shù)據(jù)庫等這些負(fù)擔(dān)。另外,隔離UI和Activity類使得應(yīng)用程序更接近MVP(Model-View-Presenter)架構(gòu)。你可以從這里了解Anko的高級功能。

雖然它有一些缺點(diǎn),如較慢的編譯和應(yīng)用程序體積大,因?yàn)樗趶?fù)用,維護(hù)和測試代碼方面打包了很多東西。

***次翻譯這么長的文章,純手打,如果有什么錯(cuò)誤的地方還請指出包涵!也是因?yàn)樽约簩otlin的興趣所以找了這篇文章來翻譯,有興趣的朋友可以看看學(xué)習(xí)一下。 

責(zé)任編輯:龐桂玉 來源: 安卓巴士Android開發(fā)者門戶
相關(guān)推薦

2015-05-20 13:12:53

ALTIBASE內(nèi)存數(shù)據(jù)庫

2024-10-09 08:48:52

2009-02-19 16:49:49

Windows 7優(yōu)點(diǎn)

2013-10-08 10:13:41

SDNOpenDayligh

2015-10-28 14:25:24

云數(shù)據(jù)中心銳捷100T平臺

2015-11-16 11:24:44

流量提速降費(fèi)運(yùn)營商

2012-02-27 09:20:43

Julia編程語言

2024-08-26 09:00:00

異構(gòu)計(jì)算多元算力CPU

2018-06-08 16:04:49

AI助理運(yùn)營商互聯(lián)網(wǎng)

2019-09-23 09:34:05

AI

2014-07-17 14:22:38

Docker云計(jì)算

2011-08-03 14:03:08

OM4光纖光纖OM4

2012-05-15 17:26:40

HP DL380 G7

2024-06-26 13:35:54

2021-11-23 15:35:01

程序員Rust開發(fā)者

2024-04-28 08:53:54

邊緣AI

2017-05-19 16:40:41

AndroidKotlin開發(fā)者

2011-01-24 13:32:16

10GBe10G以太網(wǎng)數(shù)據(jù)中心

2020-02-09 16:52:02

睡醒公司倒閉

2024-07-16 13:20:59

點(diǎn)贊
收藏

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