最近学习一下使用Kotlin 从网络获取网络图片,需要学习 HttpURLConnection的使用, 多线程(AsyncTask)的使用等 。
先说总结,获取网络图片有几种方式:
1. 直接创建一个线程获取, 会导致显示的图片错乱。
2. 使用AsyncTask , 确保正常显示图片
3. 使用Kotlin 的协程, 用看似同步的代码写异步的操作。
一、 创建根据URL 获取图片的类
第一种方式为直接创建一个线程获取,但是这种方式是明显不可行的。
// 获取网络图片实现类
class NetworkUtils {
private var picture : Bitmap ?= null
private var context: Context
companion object{
const val TAG = "NetworkUtils"
}
constructor(context: Context) {
this.context = context
}
// 获取网络图片
fun loadPicture(url: URL): Bitmap? {
// 开启一个单独线程进行网络读取
Thread(Runnable {
var bitmap: Bitmap ? = null
try {
// 根据URL 实例, 获取HttpURLConnection 实例
var httpURLConnection: HttpURLConnection = url.openConnection() as HttpURLConnection
// 设置读取 和 连接 time out 时间
httpURLConnection.readTimeout = 2000
httpURLConnection.connectTimeout = 2000
// 获取图片输入流
var inputStream = httpURLConnection.inputStream
// 获取网络响应结果
var responseCode = httpURLConnection.responseCode
// 获取正常
if (responseCode == HttpURLConnection.HTTP_OK) {
// 解析图片
bitmap = BitmapFactory.decodeStream(inputStream)
}
} catch(e: IOException) { // 捕获异常 (例如网络异常)
Log.d(TAG, "loadPicture - error: ${e?.toString()}")
}
this.picture = bitmap
}).start()
// 返回的图片可能为空- 多线程 - 上面的线程还没跑完,已经返回 结果了
return picture
}
}
第二种是使用AsyncTask.
// 三个泛型参数, 第一个为执行,第二个进度,第三个返回
class NetworkUtilsAsyncTask : AsyncTask<URL, Int, Bitmap> {
private var resultPicture: Bitmap? = null
private lateinit var context: Context
companion object {
const val TAG = "NetworkUtilsAsyncTask"
}
constructor(context: Context) {
this.context = context
}
override fun doInBackground(vararg params: URL?): Bitmap? {
return loadPicture(params[0])
}
// 获取网络图片
private fun loadPicture(url: URL?): Bitmap? {
// 开启一个单独线程进行网络读取
var bitmapFromNetwork: Bitmap? = null
url?.let {
try {
// 根据URL 实例, 获取HttpURLConnection 实例
var httpURLConnection: HttpURLConnection = url.openConnection() as HttpURLConnection
// 设置读取 和 连接 time out 时间
httpURLConnection.readTimeout = 2000
httpURLConnection.connectTimeout = 2000
// 获取图片输入流
var inputStream = httpURLConnection.inputStream
// 获取网络响应结果
var responseCode = httpURLConnection.responseCode
Log.d(TAG, "loadPicture - responseCode: $responseCode")
// 获取正常
if (responseCode == HttpURLConnection.HTTP_OK) {
// 解析图片
bitmapFromNetwork = BitmapFactory.decodeStream(inputStream)
}
} catch (e: IOException) { // 捕获异常 (例如网络异常)
Log.d(TAG, "loadPicture - error: ${e?.toString()}")
//printErrorMessage(e?.toString())
}
Log.d(TAG, "loadPicture - bitmapFromNetwork: $bitmapFromNetwork")
this.resultPicture = bitmapFromN