安卓开发:网络图片下载和显示

文章目录


前言

记录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中

上一篇:[atAGC053E]More Peaks More Fun


下一篇:共轭梯度法(Python实现)