如何将滑动显示的图像下载到设备存储中.芬兰湾的科特林



我有一个recyclerview,使用Glide显示来自Firebase实时数据库的图像。我有一个下载按钮在这个recyclerview,我希望用户能够下载这些图像一旦点击下载按钮。我听说你可以使用Glide下载图像到设备内部存储,但我不熟悉这个,所以我需要你的帮助。

适配器类

class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>) :
RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.imageView.setOnClickListener {
val intent = Intent(mContext, AbstractPreview::class.java)
intent.putExtra("abstract", abstractList[position].abstract.toString())
Toast.makeText(mContext, "Fullscreen view", Toast.LENGTH_SHORT).show()
mContext.startActivity(intent)
}
holder.downloadBtn.setOnClickListener {

}
Glide.with(mContext)
.load(abstractList[position].abstract)
.into(holder.imageView)
}
override fun getItemCount(): Int {
return abstractList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
val downloadBtn: Button = itemView.findViewById(R.id.abstractDownloadBtn)
}
companion object {
private const val Tag = "RecyclerView"
}

这是下载按钮的onClickLister。

holder.downloadBtn.setOnClickListener {
}

如你所见,我知道如何使用Glide显示图像。我只需要知道如何将这些图像下载到设备的内部存储器。

  1. 添加Okhttp依赖项

首先,你需要在你的应用gradle上设置okhttp依赖:

implementation("com.squareup.okhttp3:okhttp:4.10.0")

注意:如果您正在进行改造,则无需添加okhttp依赖项

  1. 创建下载函数

现在我们要在视图模型中添加下载逻辑,在视图模型中添加okhttp实例声明和下载函数:

注意:您可以将下载逻辑移动到存储库或任何您想要的地方,这取决于您。

class YourViewModel : ViewModel() {
// add okhttp instance to your view model or you inject it with hilt if your using dependency injection
private val okHttpClient = OkHttpClient.Builder().build()
// add this function to your view model
fun downloadImage(imageUrl: String) {
val request = Request.Builder()
.url(imageUrl)
.build()
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// Download Failed, you can show error to the user
}
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
// Download Failed, you can show error to the user
return
}
response.body?.let { responseBody ->
try {
// Convert response body to byte array
val imageByteArray = responseBody.byteStream().readBytes()
// Split image url so we can get the image name
val words = imageUrl.split("/").toTypedArray()
// Get the image name
val imageName = words.last()
// Init pathName (Downloads Directory)
val pathName = "${Environment.getExternalStorageDirectory()}/${Environment.DIRECTORY_DOWNLOADS}"
// Create New file for the image
val file = File(pathName, imageName)
// Set byteArray To Image File
file.writeBytes(imageByteArray)
} catch(e: IOException) {
// Saving Image Failed, you can show error to the user
e.printStackTrace()
}
}
}
})
}
}
  1. 将下载函数从片段传递到适配器

现在您需要将下载函数传递给lambda函数中的适配器,片段中的适配器创建应该是这样的:

val adapter = AbstractAdapter(
context = requireContext(),
abstractList = abstractList, // your list here
downloadImage = { imageUrl ->
viewModel.downloadImage(imageUrl)
}
)

你的适配器构造函数看起来像这样:

class AbstractAdapter(
private val mContext: Context, 
private val abstractList: ArrayList<Abstract>,
private val downloadImage: (imageUrl: String) -> Unit
): RecyclerView.Adapter<AbstractAdapter.ViewHolder>()
  1. 调用downloadadimage lambda在downloadBtn中点击listener

现在我们将在点击监听器

中添加downloadadimage调用
holder.downloadBtn.setOnClickListener {
val imageUrl = abstractList[position].abstract
downloadImage(imageUrl)
}
  1. 为AndroidManifest.xml添加写外部存储权限

将此权限添加到您的AndroidManifest.xml文件中,以便能够将文件添加到手机存储

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

注意:这个权限只需要sqk版本<= 28,这就是为什么我们添加了android:maxSdkVersion="28"

我希望一切都清楚了。这段代码应该会给你你想要的结果,试一下,如果有什么问题告诉我。

最新更新