base on this article:
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
- plugins {
- id("org.jetbrains.kotlin.kapt")
- }
- implementation("com.github.bumptech.glide:glide:4.16.0")
- kapt("com.github.bumptech.glide:compiler:4.16.0")
- import android.content.Context
- import android.graphics.Bitmap
- import android.os.Bundle
- import android.provider.MediaStore
- import android.util.Log
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import android.widget.TextView
- import androidx.appcompat.app.AppCompatActivity
- import androidx.appcompat.widget.AppCompatImageView
- import androidx.recyclerview.widget.GridLayoutManager
- import androidx.recyclerview.widget.RecyclerView
- import com.bumptech.glide.load.DataSource
- import com.bumptech.glide.load.engine.GlideException
- import com.bumptech.glide.request.RequestListener
- import com.bumptech.glide.request.target.Target
-
- const val PHOTO_SIZE = 150
-
- class MainActivity : AppCompatActivity() {
- private val TAG = "Glide Load"
-
- private var mItems = ArrayList
() - private var mLayoutManager: GridLayoutManager? = null
- private var mAdapter: MyAdapter? = null
- private var mGlideLoad: GlideLoad? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.recycler_view)
- init()
- }
-
- //当按了home键后,再次调出app,会进入onRestart
- override fun onRestart() {
- super.onRestart()
- Log.d(TAG, "onRestart")
- mGlideLoad?.clear()
- }
-
- override fun onStop() {
- super.onStop()
- Log.d(TAG,"onStop")
- }
-
- private fun init() {
- val spanCount = 8
-
- val rv = findViewById
(R.id.recycler_view) -
- mLayoutManager = GridLayoutManager(this, spanCount)
- rv.layoutManager = mLayoutManager
-
- mAdapter = MyAdapter(this)
- rv.adapter = mAdapter
-
- mItems = readAllImage(applicationContext)
- mAdapter?.onChange(mItems)
-
- mGlideLoad = GlideLoad(this, rv)
- }
-
- fun loadItem(holder: MyVH, position: Int) {
- val target: Target<*> = GlideApp.with(holder.itemView.context)
- .asBitmap()
- .load(mItems[position].path)
- .centerCrop()
- .addListener(object : RequestListener
{ - override fun onLoadFailed(
- e: GlideException?,
- model: Any?,
- target: Target<Bitmap>,
- isFirstResource: Boolean
- ): Boolean {
- mGlideLoad?.setLoadStatus(position, GlideLoad.NONE, null)
- return false
- }
-
- override fun onResourceReady(
- resource: Bitmap,
- model: Any,
- target: Target<Bitmap>?,
- dataSource: DataSource,
- isFirstResource: Boolean
- ): Boolean {
- holder.image.setImageBitmap(resource)
- mGlideLoad?.setLoadStatus(position, GlideLoad.NONE, null)
-
- // 特别注意此处返回是true,而不能是false。
- // 因为如果返回false,当按home键把app切入后台后,再按app图标调出app切换到前台可见,反复切换,
- // 会造成Bitmap未回收的崩溃。
- return true
- }
- }).preload(
- PHOTO_SIZE,
- PHOTO_SIZE
- )
-
- mGlideLoad?.setLoadStatus(position, GlideLoad.LOAD, target)
- }
-
- inner class MyAdapter(private val context: Context) : RecyclerView.Adapter
() { - private var items = ArrayList
() -
- fun onChange(items: ArrayList<MyData>) {
- this.items = items
-
- notifyDataSetChanged()
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
- val v = LayoutInflater.from(context).inflate(R.layout.item, parent, false)
- val params = v.layoutParams
- params.width = PHOTO_SIZE
- params.height = PHOTO_SIZE
- return MyVH(v)
- }
-
- override fun onBindViewHolder(holder: MyVH, position: Int) {
- loadItem(holder, position)
- holder.text.text = "$position"
- }
-
- override fun getItemCount(): Int {
- return items.size
- }
- }
-
- private fun readAllImage(context: Context): ArrayList
{ - val photos = ArrayList
() -
- //读取手机图片
- val cursor = context.contentResolver.query(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- null,
- null,
- null,
- null
- )
-
- while (cursor!!.moveToNext()) {
- //图片路径 uri
- val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
-
- //图片名称
- //val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
-
- //图片大小
- //val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))
-
- photos.add(MyData(path))
- }
-
- cursor.close()
-
- return photos
- }
- }
-
- class MyVH(itemView: View) : RecyclerView.ViewHolder(itemView) {
- var image: AppCompatImageView
- var text: TextView
-
- init {
- image = itemView.findViewById(R.id.image)
- text = itemView.findViewById(R.id.text)
- }
- }
-
- class MyData(var path: String)
- "1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- RelativeLayout>
- "1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="1px">
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleType="centerCrop"
- android:src="@drawable/ic_launcher_background" />
-
- <TextView
- android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:background="@android:color/holo_green_light"
- android:paddingLeft="1dp"
- android:paddingRight="1dp"
- android:text="-.-"
- android:textColor="@android:color/holo_red_dark"
- android:textSize="5dp" />
- RelativeLayout>
- import android.content.Context
- import android.util.Log
- import androidx.recyclerview.widget.GridLayoutManager
- import androidx.recyclerview.widget.RecyclerView
- import com.bumptech.glide.request.target.Target
- import java.lang.ref.WeakReference
-
- class GlideLoad {
- private val TAG = "Glide Load"
-
- companion object {
- const val NONE: Int = 0
- const val LOAD: Int = 1
- }
-
- private var mLayoutManager: GridLayoutManager? = null
- private var mRecyclerView: RecyclerView? = null
- private var mVisibleItemPosition: IntArray? = null
- private var mContext: Context? = null
-
- private var mStatusItems: ArrayList
? = ArrayList() -
- constructor(ctx: Context?, rv: RecyclerView?) {
- mContext = ctx
- mRecyclerView = rv
-
- repeat(mRecyclerView?.adapter?.itemCount!!) {
- mStatusItems?.add(Status())
- }
-
- mLayoutManager = mRecyclerView?.layoutManager as? GridLayoutManager
- mRecyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
- override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
- super.onScrolled(recyclerView, dx, dy)
- mVisibleItemPosition = getVisibleItemPosition()
- }
- })
- }
-
- fun setLoadStatus(pos: Int, status: Int, target: Target<*>?) {
- mStatusItems!![pos].position = pos
- mStatusItems!![pos].status = status
- if (target != null) {
- mStatusItems!![pos].targetRef = WeakReference(target)
- } else {
- mStatusItems!![pos].targetRef = null
- }
- }
-
- fun clear() {
- Log.d(TAG, "可见区域 ${mVisibleItemPosition!![0]}->${mVisibleItemPosition!![1]}")
-
- for (i in 0 until mStatusItems!!.size) {
- if (i !in mVisibleItemPosition!![0]..mVisibleItemPosition!![1]) {
- if (mStatusItems!![i].status == LOAD) {
- mStatusItems!![i].targetRef?.get()?.let {
- GlideApp.with(mContext!!).clear(it)
- }
-
- mStatusItems!![i].status = NONE
- mStatusItems!![i].targetRef = null
- }
- }
- }
- }
-
- private fun getVisibleItemPosition(): IntArray {
- val first = mLayoutManager?.findFirstVisibleItemPosition()
- val last = mLayoutManager?.findLastVisibleItemPosition()
- return intArrayOf(first!!, last!!)
- }
-
- class Status {
- var targetRef: WeakReference
>? = null - var status = NONE
- var position = 0
- }
- }
- import android.content.Context
- import android.util.Log
- import com.bumptech.glide.GlideBuilder
- import com.bumptech.glide.annotation.GlideModule
- import com.bumptech.glide.module.AppGlideModule
-
- @GlideModule
- class MyModule : AppGlideModule() {
- override fun applyOptions(context: Context, builder: GlideBuilder) {
- builder.setLogLevel(Log.DEBUG)
- }
-
- override fun isManifestParsingEnabled(): Boolean {
- return false
- }
- }