參考:《第一行代碼:Android》第2版——郭霖
注1:本文為原創,例子可參考郭前輩著作:《第一行代碼:Android》
注2:本文不贅述android開發的基本理論,不介紹入門知識,不介紹Android Studio基本安裝,開門見山,直接使用kotlin改寫郭前輩的《第一行代碼:Android》中的部分例子,有機會的話自己做一些新例子出來!
注3:本文基本以kotlin語言作為Android開發,偶爾涉及java作為對比
注4:開發基於Android Studio 3.0,並且新建項目時勾選“support kotlin”
看看精彩世界——使用網絡技術
原書9.2節:看看精彩世界——使用網絡技術(書p312)
原書采用了OkHttp開源項目作為請求類庫
我改為使用kotlin對Java.Net類擴展的URL類!
一些小知識:
kotlin是基於JVM的語言,他不像scala語言,重新構建了自己的生態,kotlin直接擴展了java的類庫,他的宗旨:“java有則用之,無則擴展之”,所以他能做到與java的100%兼容,這個優勢同樣被一起帶入了他的Android開發鄰域
(注:kotlin已成為了Google官推語言)
Anko類庫:
anko類庫不是kotlin自帶的標准庫,需要在gradle中添加擴展,gradle會自動下載anko和處理他的依賴
官網對anko的描述(也許你暫時不感興趣,可以跳過):https://github.com/Kotlin/anko
尋找anko:
上這個網址,搜索anko即可
http://mvnrepository.com/search?q=anko
點擊如圖箭頭里的包:
需要用到的是上圖中的其中三個,anko-sdk可以選擇23或者15,我選擇的是15。
另外兩個,一個個點進去,選擇gradle,復制里面的代碼:
復制到這里:
並且自己改成成android gradle的格式,什么是android的格式?
參考這個文件原有的gradle dependencies寫法即可,注意去掉結尾的beta!
build.gradle(Module:app):
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.squareup.okhttp3:okhttp:3.8.0'
compile 'org.jetbrains.anko:anko-sdk15:0.9'
compile 'org.jetbrains.anko:anko-support-v4:0.9'
compile 'org.jetbrains.anko:anko-appcompat-v7:0.9'
}
點擊sync gradle,把類庫同步到本地
記得要配置Manifest.xml提供網絡訪問的權限!
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.cslg.networktest">
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
......
</application>
........
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.cslg.networktest.MainActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="http://guolin.tech/api/china/16/116"
/>
<Button
android:id="@+id/get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="獲取網絡數據" />
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="從url獲得的數據"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ScrollView>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
布局文件提供了一個EditText,一個TextView,一個Button,一個ImageView,一個ScrollView
EditText:用戶可以輸入任何可以返回字符串或者文件字節的網址
Button:點擊后開始請求
TextView:顯示返回的字符串
ImageView:顯示網址的圖片文件
ScrollView:提供給TextView用,有可能字符串過長溢出,這個控件可以顯示為滾動的文本
kotlin
MainActivity.kt:
package cn.cslg.networktest
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import org.jetbrains.anko.*
import org.jetbrains.anko.custom.async
import java.net.URL
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text = find<TextView>(R.id.text)
val Btn = find<Button>(R.id.get)
val url = find<EditText>(R.id.url)
val img = find<ImageView>(R.id.img)
Btn.onClick({
val url = url.text.toString()
async {
val byteArrayIn = URL(url).readBytes()
var s = String(byteArrayIn)
uiThread { text.setText(s) }
}
})
}
}
分析:
可以看到上述代碼引入了anko包,這使得kotlin對布局的獲取和操作更加的簡單直觀
使用 find
使用 var(可變)或者val(不可變)來聲明並且直接獲得對象的引用,kotlin編譯器將會自動推斷變量類型!
這些find,onClick方法都是anko包提供的
是不是比findViewById和那個xxxListener簡單很多
kotlin還可以用lambada表達式替代原來java看着冗長的匿名類(閉包)
事實上,這里是直接向onClick傳入了一個fun,即函數對象!它將在onClick觸發后去執行
接下來是真正對網絡世界的請求:
URL類是kotlin對java.net庫的擴展,用於網絡請求,構造方法將會生成一個URL對象,里面有倆方法:
參考:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.net.-u-r-l/
使用URL.readText可以直接獲取網站返回的字符串String,一般用於json的獲取
使用URL.readBytes可以將網站返回的內容按字節ByteArray獲取,可用於圖片,文件的獲取
上述使用了Bytes是為了后面獲得一張在線圖片准備,如果想直接獲得json字符串的話,使用readText:
async {
val s = URL(url).readText()
uiThread { text.setText(s) }
}
效果
輸入網址,獲得相應數據,此例獲得json
獲取文件
上面實現的是獲取String,那么獲取文件呢
以圖片文件為例,直接顯示在ImageView控件當中
修改async下的代碼即可
async {
val data = URL(url).readBytes()
if (data != null) {
uiThread {
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)// bitmap
imageView.setImageBitmap(bitmap)
toast("success")
}
} else {
toast("image error")
}
}
分析:
這次為了獲得文件,必須使用readBytes方法,他會傳回一個ByteArray(字節數組)
然后使用BitmapFactory下的decodeByteArray方法將ByteArray轉換為圖片
效果
試着在EditText輸入圖片的地址: