From 93e37ec8e63330daa2188463a100e4aba99561a3 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 19 Nov 2016 22:05:44 +0100 Subject: [PATCH] make obtaining photo and video asynchronous --- .../gallery/activities/MediaActivity.kt | 99 +++++-------------- .../gallery/adapters/MediaAdapter.kt | 7 +- .../gallery/asynctasks/GetMediaAsynctask.kt | 86 ++++++++++++++++ 3 files changed, 111 insertions(+), 81 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/gallery/asynctasks/GetMediaAsynctask.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/MediaActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/MediaActivity.kt index f7c0aa43a..ab2798df5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/MediaActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/MediaActivity.kt @@ -3,12 +3,10 @@ package com.simplemobiletools.gallery.activities import android.app.Activity import android.app.WallpaperManager import android.content.Intent -import android.database.Cursor import android.graphics.Bitmap import android.graphics.Color import android.net.Uri import android.os.Bundle -import android.provider.MediaStore import android.support.design.widget.Snackbar import android.util.Log import android.view.Menu @@ -22,6 +20,7 @@ import com.simplemobiletools.filepicker.extensions.* import com.simplemobiletools.gallery.Constants import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.adapters.MediaAdapter +import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog import com.simplemobiletools.gallery.extensions.getHumanizedFilename import com.simplemobiletools.gallery.models.Medium @@ -29,7 +28,6 @@ import kotlinx.android.synthetic.main.activity_media.* import java.io.File import java.io.IOException import java.util.* -import java.util.regex.Pattern class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.MediaOperationsListener { companion object { @@ -45,6 +43,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media private var mIsGetImageIntent = false private var mIsGetVideoIntent = false private var mIsGetAnyIntent = false + private var mIsGettingMedia = false } override fun onCreate(savedInstanceState: Bundle?) { @@ -56,7 +55,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media mIsGetAnyIntent = getBooleanExtra(Constants.GET_ANY_INTENT, false) } - media_holder.setOnRefreshListener({ refreshDir() }) + media_holder.setOnRefreshListener({ getMedia() }) mPath = intent.getStringExtra(Constants.DIRECTORY) mToBeDeleted = ArrayList() mMedia = ArrayList() @@ -74,19 +73,15 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media private fun tryloadGallery() { if (hasStoragePermission()) { - initializeGallery() + val dirName = getHumanizedFilename(mPath) + title = dirName + getMedia() } else { finish() } } private fun initializeGallery() { - val newMedia = getMedia() - if (newMedia.toString() == mMedia.toString()) { - return - } - - mMedia = newMedia if (isDirEmpty()) return @@ -97,9 +92,6 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media media_grid.adapter = adapter media_grid.setOnTouchListener(this) mIsSnackbarShown = false - - val dirName = getHumanizedFilename(mPath) - title = dirName } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -141,7 +133,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media private fun showSortingDialog() { ChangeSortingDialog(this, false, object : ChangeSortingDialog.OnChangeSortingListener { override fun sortingChanged() { - initializeGallery() + getMedia() } }) } @@ -167,55 +159,23 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media } } - private fun getMedia(): ArrayList { - val media = ArrayList() - val invalidFiles = ArrayList() - for (i in 0..1) { - if (mIsGetVideoIntent && i == 0) - continue + private fun getMedia() { + if (mIsGettingMedia) + return - var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI - if (i == 1) { - if (mIsGetImageIntent) - continue - - uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI - } - val where = "${MediaStore.Images.Media.DATA} LIKE ? " - val args = arrayOf("$mPath%") - val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED) - val pattern = "${Pattern.quote(mPath)}/[^/]*" - var cursor: Cursor? = null - - try { - cursor = contentResolver.query(uri, columns, where, args, null) - - if (cursor != null && cursor.moveToFirst()) { - val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA) - do { - val curPath = cursor.getString(pathIndex) ?: continue - - if (curPath.matches(pattern.toRegex()) && !mToBeDeleted.contains(curPath.toLowerCase())) { - val file = File(curPath) - if (file.exists()) { - val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED) - val timestamp = cursor.getLong(dateIndex) - media.add(Medium(file.name, curPath, i == 1, timestamp, file.length())) - } else { - invalidFiles.add(file) - } - } - } while (cursor.moveToNext()) + mIsGettingMedia = true + GetMediaAsynctask(applicationContext, mPath, mIsGetVideoIntent, mIsGetImageIntent, mToBeDeleted, object : GetMediaAsynctask.GetMediaListener { + override fun gotMedia(media: ArrayList) { + mIsGettingMedia = false + media_holder.isRefreshing = false + if (media.toString() == mMedia.toString()) { + return } - } finally { - cursor?.close() - } - } - Medium.sorting = mConfig.sorting - media.sort() - scanFiles(invalidFiles) {} - return media + mMedia = media + initializeGallery() + } + }).execute() } private fun isDirEmpty(): Boolean { @@ -239,7 +199,7 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media } private fun notifyDeletion(cnt: Int) { - mMedia = getMedia() + getMedia() if (mMedia.isEmpty()) { deleteFiles() @@ -299,14 +259,12 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media mSnackbar!!.dismiss() mIsSnackbarShown = false mToBeDeleted.clear() - mMedia = getMedia() updateMediaView() } private fun updateMediaView() { if (!isDirEmpty()) { - (media_grid.adapter as MediaAdapter).updateMedia(mMedia) - initializeGallery() + getMedia() } } @@ -359,15 +317,6 @@ class MediaActivity : SimpleActivity(), View.OnTouchListener, MediaAdapter.Media } override fun refreshItems() { - refreshDir() - } - - private fun refreshDir() { - val dir = File(mPath) - if (dir.isDirectory) { - scanPath(mPath) {} - } - initializeGallery() - media_holder.isRefreshing = false + getMedia() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt index ef52bb7aa..d0b7d4953 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/adapters/MediaAdapter.kt @@ -27,7 +27,7 @@ import kotlinx.android.synthetic.main.photo_video_tmb.view.* import java.io.File import java.util.* -class MediaAdapter(val activity: SimpleActivity, var media: MutableList, val listener: MediaOperationsListener?, val itemClick: (Medium) -> Unit) : +class MediaAdapter(val activity: SimpleActivity, val media: MutableList, val listener: MediaOperationsListener?, val itemClick: (Medium) -> Unit) : RecyclerView.Adapter() { val multiSelector = MultiSelector() val views = ArrayList() @@ -162,11 +162,6 @@ class MediaAdapter(val activity: SimpleActivity, var media: MutableList, notifyDataSetChanged() } - fun updateMedia(media: MutableList) { - this.media = media - notifyDataSetChanged() - } - override fun getItemCount() = media.size class ViewHolder(view: View, val itemClick: (Medium) -> (Unit)) : SwappingHolder(view, MultiSelector()) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/asynctasks/GetMediaAsynctask.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/asynctasks/GetMediaAsynctask.kt new file mode 100644 index 000000000..6636ef664 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/asynctasks/GetMediaAsynctask.kt @@ -0,0 +1,86 @@ +package com.simplemobiletools.gallery.asynctasks + +import android.content.Context +import android.database.Cursor +import android.os.AsyncTask +import android.provider.MediaStore +import com.simplemobiletools.filepicker.extensions.scanFiles +import com.simplemobiletools.gallery.Config +import com.simplemobiletools.gallery.models.Medium +import java.io.File +import java.lang.ref.WeakReference +import java.util.* +import java.util.regex.Pattern + +class GetMediaAsynctask(val context: Context, val mPath: String, val isPickVideo: Boolean, val isPickImage: Boolean, + val mToBeDeleted: List, val listener: GetMediaListener) : AsyncTask>() { + lateinit var mConfig: Config + lateinit var mListener: WeakReference + + override fun onPreExecute() { + super.onPreExecute() + mConfig = Config.newInstance(context) + mListener = WeakReference(listener) + } + + override fun doInBackground(vararg params: Void): ArrayList { + val media = ArrayList() + val invalidFiles = ArrayList() + for (i in 0..1) { + if (isPickVideo && i == 0) + continue + + var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI + if (i == 1) { + if (isPickImage) + continue + + uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI + } + val where = "${MediaStore.Images.Media.DATA} LIKE ?" + val args = arrayOf("$mPath%") + val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED) + val pattern = "${Pattern.quote(mPath)}/[^/]*" + var cursor: Cursor? = null + + try { + cursor = context.contentResolver.query(uri, columns, where, args, null) + + if (cursor != null && cursor.moveToFirst()) { + val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA) + do { + val curPath = cursor.getString(pathIndex) ?: continue + + if (curPath.matches(pattern.toRegex()) && !mToBeDeleted.contains(curPath.toLowerCase())) { + val file = File(curPath) + if (file.exists()) { + val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED) + val timestamp = cursor.getLong(dateIndex) + media.add(Medium(file.name, curPath, i == 1, timestamp, file.length())) + } else { + invalidFiles.add(file) + } + } + } while (cursor.moveToNext()) + } + } finally { + cursor?.close() + } + } + + Medium.sorting = mConfig.sorting + media.sort() + context.scanFiles(invalidFiles) {} + return media + } + + override fun onPostExecute(media: ArrayList) { + super.onPostExecute(media) + val listener = mListener.get() + listener?.gotMedia(media) + } + + interface GetMediaListener { + fun gotMedia(media: ArrayList) + } +}