文章目录
前言
记录APP从无到有下载网络图片并做展示的方法:创建一个图片加载器负责下载和显示。
一、图片加载器
图片加载器的功能包括图片下载和图片的缓存。缓存类的设计如下,使用LruCache类即可,缓存的最大值设定为为运行时内存的四分之一。关于LruCache的使用和原理可自行百度。
class ImageCache {
lateinit var imageCache: LruCache<String, Bitmap>
init {
initCache()
}
private fun initCache() {
val maxMemory = Runtime.getRuntime().maxMemory() / 1024
val cacheSize = maxMemory / 4
imageCache = object : LruCache<String, Bitmap>(cacheSize.toInt()) {
override fun sizeOf(key: String?, value: Bitmap?): Int {
return (value?.rowBytes?.times(value.height) ?: 0) / 1024
}
}
}
fun putImage(url: String, bitmap: Bitmap) {
imageCache.put(url, bitmap)
}
fun getImage(url: String): Bitmap? {
return imageCache.get(url)
}
}
图片下载类的设计如下,包括发起任务、网络连接和图片显示,先上代码:
class ImageLoader {
val imageCache = ImageCache()
//Android禁止任何主线程网络连接行为
val executeService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
val handler: Handler = Handler(Looper.getMainLooper())
//使用时调用该方法,触发网络下载之前可先在imageCache中查找,没有再下载以节约资源。
fun showImage(url: String, imageView: ImageView) {
var bitmap = imageCache.getImage(url)
if (bitmap != null) {
imageView.setImageBitmap(bitmap)
return
}
imageView.tag = url
executeService.submit {
Log.d(TAG,"service submit")
bitmap = downloadImage(url)
if (bitmap == null) return@submit
else if (imageView.tag == url) {
updateImage(bitmap!!, imageView)
}
//下载完成后会将图片放到缓存中
imageCache.putImage(url, bitmap!!)
}
}
//下载图片的方法:建立连接,获取输入流并进行解析
private fun downloadImage(url: String): Bitmap? {
val imageURL = URL(url)
var bitmap: Bitmap? = null
try {
val connect = imageURL.openConnection() as HttpURLConnection
bitmap = BitmapFactory.decodeStream(connect.inputStream)
Log.d(TAG, "bitmap is empty: $bitmap")
connect.disconnect()
} catch (e: Exception) {
e.printStackTrace()
}
return bitmap
}
private fun updateImage(bitmap: Bitmap, imageView: ImageView) {
handler.post {
imageView.setImageBitmap(bitmap)
}
}
在MainActivity中进行实践:
class MainActivity : AppCompatActivity() {
lateinit var image_1: ImageView
lateinit var loadBtn: Button
//这是我测试时使用的自己QQ空间的一张图片的路径,自己可以修改
val path: String =
"http://photonj.photo.store.qq.com/psc?/sa14V12nyLUU3BNRg8322f777c023ef37d07ee96b7f448d4636a14V13cSHUM24lcsx/A845Uywr4tMMRU*7oNCSQ4nLkHSs4ffNYPeOJiLIo2gfhNAnSQ2jNS1KmyxKWGCwK0u8HAn65FJKPuhvIVtY*PB0TOKpigiy6DqU0QkLyxw!/b&bo=OASgBQAAAAARN5k!&rf=viewer_4"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
image_1 = findViewById(R.id.image_1)
loadBtn = findViewById(R.id.btn_load)
loadBtn.setOnClickListener {
ImageLoader().showImage(path, image_1)
}
}
此时编译和运行代码可能会爆出以下错误:
第一个:
java.io.IOException: Cleartext HTTP traffic to XXXXXX not permitted
解决方法:申请网络权限,在AndroidMenifest中添加:
uses-permission android:name="android.permission.INTERNET
android:usesCleartextTraffic=“true”
样式如下:
<manifest
……省略
<uses-permission android:name="android.permission.INTERNET"/>
<application
……省略
android:usesCleartextTraffic="true">
……省略
</application>
</manifest>
第二个:
java.net.UnknownHostException: Unable to resolve host "photonj.photo.store.qq.com": No address associated with hostname
解决方法:保证手机联网
最终,下载的图片会显示在ImageView中