You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Coil从URL获取Bitmap?求助结合Palette API取色的实现

从URL加载Bitmap并使用Palette API提取颜色的完整方案

Got it, let's walk through this step by step — first loading a Bitmap from a URL, then using the Palette API to pull out those colors. I'll cover both native Android code and a simpler library approach since network and bitmap handling can get messy otherwise.

1. 先搞定从URL加载Bitmap

First off, you need to add the internet permission to your AndroidManifest.xml—can't load network images without it:

<uses-permission android:name="android.permission.INTERNET" />

原生实现(Kotlin + Coroutines)

Since AsyncTask is deprecated, using Kotlin Coroutines is the modern way to handle background network work. Here's a suspend function that safely loads a Bitmap from a URL:

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL

suspend fun loadBitmapFromUrl(imageUrl: String): Bitmap? {
    return withContext(Dispatchers.IO) {
        var connection: HttpURLConnection? = null
        var inputStream: InputStream? = null
        try {
            val url = URL(imageUrl)
            connection = url.openConnection() as HttpURLConnection
            connection.doInput = true
            connection.connect()
            inputStream = connection.inputStream
            BitmapFactory.decodeStream(inputStream)
        } catch (e: IOException) {
            // Log the error instead of just printing it in production!
            e.printStackTrace()
            null
        } finally {
            // Always close streams and connections to avoid leaks
            inputStream?.close()
            connection?.disconnect()
        }
    }
}

Pro tip: Call this function from a coroutine scope (like viewModelScope in a ViewModel or lifecycleScope in an Activity/Fragment) to avoid lifecycle issues.

更省心的方案:用Glide

If you don't want to handle all the network/stream boilerplate, using a library like Glide is way simpler—it handles caching, thread management, and error cases out of the box:

import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition

Glide.with(yourContext)
    .asBitmap()
    .load(imageUrl)
    .into(object : CustomTarget<Bitmap>() {
        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
            // We've got our Bitmap—time to use Palette!
            processBitmapWithPalette(resource)
        }

        override fun onLoadCleared(placeholder: Drawable?) {
            // Clean up any resources if needed
        }
    })

Don't forget to add Glide's dependency to your build.gradle (Module level):

implementation "com.github.bumptech.glide:glide:4.15.1"
annotationProcessor "com.github.bumptech.glide:compiler:4.15.1"

2. 使用Palette API提取颜色

Once you have your Bitmap, using Palette is straightforward. First, make sure you have the dependency (it's included in Material Components, or you can add it separately):

// If using Material Components (recommended)
implementation "com.google.android.material:material:1.9.0"

// Or standalone Palette
implementation "androidx.palette:palette:1.0.0"

Here's how to generate a Palette and extract common color swatches:

import androidx.palette.graphics.Palette

fun processBitmapWithPalette(bitmap: Bitmap) {
    // Generate Palette asynchronously (don't block the main thread!)
    Palette.from(bitmap).generate { palette ->
        palette?.let {
            // Get different color types based on your needs
            val vibrantColor = it.vibrantSwatch?.rgb
            val mutedColor = it.mutedSwatch?.rgb
            val lightVibrantColor = it.lightVibrantSwatch?.rgb
            val darkMutedColor = it.darkMutedSwatch?.rgb

            // Each swatch also has text colors that contrast well with the background
            val vibrantTextColor = it.vibrantSwatch?.titleTextColor

            // Apply these to your UI—make sure to run on the main thread!
            vibrantColor?.let { color ->
                yourToolbar.setBackgroundColor(color)
                yourTitleTextView.setTextColor(vibrantTextColor ?: color)
            }
        }
    }
}

If you need to generate Palette synchronously (only do this in a background thread!), use Palette.from(bitmap).generate() instead of the callback version.

关键注意事项

  • Thread Safety: Never run network calls, Bitmap decoding, or synchronous Palette generation on the main thread—this will cause ANRs (Application Not Responding).
  • Memory Management: Bitmaps are memory-heavy. If you're done with a Bitmap, call bitmap.recycle() to free up memory (but only if you're sure no other parts of your app are using it).
  • Error Handling: Always handle cases where the Bitmap fails to load (returned null) or Palette can't extract any colors (palette is null).

内容的提问来源于stack exchange,提问作者Chintan Parmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:02:50