From 86ddfb02cb989ab5b6990e518640ab82c107bc37 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 30 Aug 2017 12:13:38 -0400 Subject: fix/mediapicker (#50) * Bring all glide request managers to one instance * Switch to test implementation * Check if parent is null for searchview * Ensure open close runs on ui thread * Make glide contract internal * Update changelog * Update version --- android-lib.gradle | 8 ++++---- docs/Changelog.md | 3 +++ gradle.properties | 2 +- .../ca/allanwang/kau/mediapicker/GlideHelper.kt | 18 ++++++++++++++++++ .../ca/allanwang/kau/mediapicker/MediaItem.kt | 6 +++--- .../ca/allanwang/kau/mediapicker/MediaItemBasic.kt | 6 +++--- .../ca/allanwang/kau/mediapicker/MediaPickerCore.kt | 11 +++++++++-- sample/src/main/res/xml/kau_changelog.xml | 4 +++- .../ca/allanwang/kau/searchview/SearchView.kt | 21 +++++++++++---------- 9 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt diff --git a/android-lib.gradle b/android-lib.gradle index a8417c0..d968dd4 100644 --- a/android-lib.gradle +++ b/android-lib.gradle @@ -70,10 +70,10 @@ android { } dependencies { - androidTestCompile("com.android.support.test:runner:${TEST_RUNNER}") { + androidTestImplementation("com.android.support.test:runner:${TEST_RUNNER}") { exclude group: 'com.android.support', module: 'support-annotations' } - androidTestCompile "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" - testCompile "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" - testCompile "junit:junit:${JUNIT}" + androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${KOTLIN}" + testImplementation "junit:junit:${JUNIT}" } \ No newline at end of file diff --git a/docs/Changelog.md b/docs/Changelog.md index 63927a7..aa37c4d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,9 @@ ## v3.4.0 * Update to gradle 4.x; api and implementation rather than compile * Update dependencies +* :searchview: Ensure reveals are called on the UI thread +* :searchview: Check that searchview has a parent before checking card state +* :mediapicker: Reuse request manager from activity ## v3.3.2 * :kpref-activity: Add visibility toggle to Core contract. Items can override this to show/hide given preferences based on boolean callbacks. diff --git a/gradle.properties b/gradle.properties index ad3a84a..9a1177d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,7 +23,7 @@ TARGET_SDK=26 BUILD_TOOLS=26.0.1 ANDROID_SUPPORT_LIBS=26.0.1 -VERSION_NAME=3.3.3 +VERSION_NAME=3.4.0 KOTLIN=1.1.4-2 ABOUT_LIBRARIES=5.9.7 diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt new file mode 100644 index 0000000..8bb341c --- /dev/null +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt @@ -0,0 +1,18 @@ +package ca.allanwang.kau.mediapicker + +import android.view.View +import com.bumptech.glide.Glide +import com.bumptech.glide.RequestManager + +/** + * Created by Allan Wang on 29/08/2017. + * + * Basic helper to fetch the [RequestManager] from the activity if it exists, before creating another one + */ +internal interface GlideContract { + fun glide(v: View): RequestManager +} + +internal class GlideDelegate : GlideContract { + override fun glide(v: View) = ((v.context as? MediaPickerCore<*>)?.glide ?: Glide.with(v))!! +} \ No newline at end of file diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt index b6f3721..0431465 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt @@ -16,7 +16,7 @@ import com.mikepenz.fastadapter.FastAdapter * Created by Allan Wang on 2017-07-04. */ class MediaItem(val data: MediaModel) - : KauIItem(R.layout.kau_iitem_image, { ViewHolder(it) }) { + : KauIItem(R.layout.kau_iitem_image, { ViewHolder(it) }), GlideContract by GlideDelegate() { private var failedToLoad = false @@ -38,7 +38,7 @@ class MediaItem(val data: MediaModel) override fun bindView(holder: ViewHolder, payloads: List?) { super.bindView(holder, payloads) - Glide.with(holder.itemView) + glide(holder.itemView) .load(data.data) .applyMediaOptions(holder.itemView.context) .listener(object : RequestListener { @@ -59,7 +59,7 @@ class MediaItem(val data: MediaModel) override fun unbindView(holder: ViewHolder) { super.unbindView(holder) - Glide.with(holder.itemView).clear(holder.container.imageBase) + glide(holder.itemView).clear(holder.container.imageBase) holder.container.removeBlurInstantly() failedToLoad = false } diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt index e546afb..2d6cefa 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt @@ -22,7 +22,7 @@ import com.mikepenz.fastadapter.FastAdapter * Created by Allan Wang on 2017-07-04. */ class MediaItemBasic(val data: MediaModel) - : KauIItem(R.layout.kau_iitem_image_basic, { ViewHolder(it) }) { + : KauIItem(R.layout.kau_iitem_image_basic, { ViewHolder(it) }), GlideContract by GlideDelegate() { companion object { @SuppressLint("NewApi") @@ -40,7 +40,7 @@ class MediaItemBasic(val data: MediaModel) override fun bindView(holder: ViewHolder, payloads: List?) { super.bindView(holder, payloads) - Glide.with(holder.itemView) + glide(holder.itemView) .load(data.data) .applyMediaOptions(holder.itemView.context) .listener(object : RequestListener { @@ -58,7 +58,7 @@ class MediaItemBasic(val data: MediaModel) override fun unbindView(holder: ViewHolder) { super.unbindView(holder) - Glide.with(holder.itemView).clear(holder.image) + glide(holder.itemView).clear(holder.image) } class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt index eada173..d518b78 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt @@ -27,6 +27,7 @@ import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.utils.dimenPixelSize import ca.allanwang.kau.utils.toast import com.bumptech.glide.Glide +import com.bumptech.glide.RequestManager import com.mikepenz.fastadapter.IItem import com.mikepenz.fastadapter.adapters.HeaderAdapter import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter @@ -103,6 +104,7 @@ abstract class MediaPickerCore>( const val CACHE_SIZE = 80 } + lateinit var glide: RequestManager private var hasPreloaded = false private var prefetcher: Future<*>? = null @@ -113,6 +115,11 @@ abstract class MediaPickerCore>( */ val extraSpace: Int by lazy { resources.displayMetrics.heightPixels } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + glide = Glide.with(this) + } + fun initializeRecycler(recycler: RecyclerView) { val adapterWrapper = HeaderAdapter() adapterWrapper.wrap(adapter) @@ -176,7 +183,7 @@ abstract class MediaPickerCore>( hasPreloaded = true prefetcher = doAsync { models.subList(0, Math.min(models.size, 50)).map { it.data }.forEach { - val target = Glide.with(this@MediaPickerCore).load(it) + val target = glide.load(it) .applyMediaOptions(this@MediaPickerCore) .submit() try { @@ -184,7 +191,7 @@ abstract class MediaPickerCore>( } catch (ignored: InterruptedException) { } catch (ignored: ExecutionException) { } finally { - Glide.with(this@MediaPickerCore).clear(target) + glide.clear(target) } } } diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index 87611f8..d5a653d 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -9,7 +9,9 @@ - + + + diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt index 491fbe9..dabf4bc 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.Color import android.support.annotation.ColorInt -import android.support.annotation.ColorRes import android.support.annotation.IdRes import android.support.transition.ChangeBounds import android.support.transition.TransitionManager @@ -215,7 +214,7 @@ class SearchView @JvmOverloads constructor( val adapter = FastItemAdapter() var menuItem: MenuItem? = null val isOpen: Boolean - get() = isAttachedToWindow && card.isVisible + get() = parent != null && card.isVisible /* * Ripple start points and search view offset @@ -306,7 +305,7 @@ class SearchView @JvmOverloads constructor( val menuItem = menu.findItem(id) ?: throw IllegalArgumentException("Menu item with given id doesn't exist") if (menuItem.icon == null) menuItem.icon = GoogleMaterial.Icon.gmd_search.toDrawable(context, 18, menuIconColor) card.gone() - menuItem.setOnMenuItemClickListener { configureCoords(it); revealOpen(); true } + menuItem.setOnMenuItemClickListener { revealOpen(); true } shadow.setOnClickListener { revealClose() } this.menuItem = menuItem return this @@ -322,7 +321,8 @@ class SearchView @JvmOverloads constructor( menuItem = null } - private fun configureCoords(item: MenuItem) { + private fun configureCoords(item: MenuItem?) { + item ?: return if (parent !is ViewGroup) return val view = parentViewGroup.findViewById(item.itemId) ?: return val locations = IntArray(2) @@ -334,7 +334,7 @@ class SearchView @JvmOverloads constructor( override fun onPreDraw(): Boolean { view.viewTreeObserver.removeOnPreDrawListener(this) card.setMarginTop(menuY - card.height / 2) - return false + return true } }) } @@ -372,14 +372,15 @@ class SearchView @JvmOverloads constructor( } fun revealOpen() { - if (isOpen) return - post { + if (parent == null || isOpen) return + context.runOnUiThread { /** * The y component is relative to the cardView, but it hasn't been drawn yet so its own height is 0 * We therefore use half the menuItem height, which is a close approximation to our intended value * The cardView matches the parent's width, so menuX is correct */ - configs.openListener?.invoke(this) + configureCoords(menuItem) + configs.openListener?.invoke(this@SearchView) shadow.fadeIn() editText.showKeyboard() card.circularReveal(menuX, menuHalfHeight, duration = configs.revealDuration) { @@ -390,8 +391,8 @@ class SearchView @JvmOverloads constructor( } fun revealClose() { - if (!isOpen) return - post { + if (parent == null || !isOpen) return + context.runOnUiThread { shadow.fadeOut(duration = configs.transitionDuration) cardTransition { addEndListener { -- cgit v1.2.3