From 9dcc5bcbe7ce8d0a4bdb804a4c6374c52db23398 Mon Sep 17 00:00:00 2001 From: wp <517309507@qq.com> Date: Wed, 7 Sep 2022 15:28:57 +0800 Subject: [PATCH] opt demo code --- .../demo/business/SimpleViewerCustomizer.kt | 13 +- .../demo/core/LifecycleDisposable.kt | 15 -- .../demo/core/viewer/SimpleImageLoader.kt | 2 +- .../imageviewer/demo/utils/extensions.kt | 150 ++++++++++++------ app/src/main/res/values/ids.xml | 2 + 5 files changed, 112 insertions(+), 70 deletions(-) delete mode 100644 app/src/main/java/com/github/iielse/imageviewer/demo/core/LifecycleDisposable.kt diff --git a/app/src/main/java/com/github/iielse/imageviewer/demo/business/SimpleViewerCustomizer.kt b/app/src/main/java/com/github/iielse/imageviewer/demo/business/SimpleViewerCustomizer.kt index 2661d06..6704973 100644 --- a/app/src/main/java/com/github/iielse/imageviewer/demo/business/SimpleViewerCustomizer.kt +++ b/app/src/main/java/com/github/iielse/imageviewer/demo/business/SimpleViewerCustomizer.kt @@ -46,7 +46,7 @@ class SimpleViewerCustomizer : LifecycleEventObserver, VHCustomizer, OverlayCust private var testDataViewModel: TestDataViewModel? = null private var viewerViewModel: ImageViewerActionViewModel? = null private var videoTask: Disposable? = null - private var lastVideoVH: RecyclerView.ViewHolder? = null + private var lastVideoVH: VideoViewHolder? = null private var binding: LayoutIndicatorBinding? = null private var currentPosition = -1 @@ -133,19 +133,18 @@ class SimpleViewerCustomizer : LifecycleEventObserver, VHCustomizer, OverlayCust private fun processSelectVideo(viewHolder: RecyclerView.ViewHolder) { videoTask?.dispose() - lastVideoVH?.itemView?.findViewById(R.id.videoView)?.reset() + lastVideoVH?.binding?.videoView?.reset() when (viewHolder) { is VideoViewHolder -> { - val videoView = viewHolder.itemView.findViewById(R.id.videoView) - - val task = object : ObserverAdapter(videoView?.lifecycleOwner?.lifecycle) { + val videoView = viewHolder.binding.videoView + val task = object : ObserverAdapter(videoView.lifecycleOwner.lifecycle) { override fun onNext(t: Long) { if (ViewerHelper.simplePlayVideo) { - videoView?.resume() + videoView.resume() } else { val playerControlView = viewHolder.itemView.findViewById(R.id.playerControlView) - playerControlView?.player = videoView?.player() + playerControlView?.player = videoView.player() } } } diff --git a/app/src/main/java/com/github/iielse/imageviewer/demo/core/LifecycleDisposable.kt b/app/src/main/java/com/github/iielse/imageviewer/demo/core/LifecycleDisposable.kt deleted file mode 100644 index b61af86..0000000 --- a/app/src/main/java/com/github/iielse/imageviewer/demo/core/LifecycleDisposable.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.iielse.imageviewer.demo.core - -import androidx.lifecycle.* -import io.reactivex.disposables.Disposable - -class LifecycleDisposable( - private val lifecycle: Lifecycle, - private val disposable: Disposable) : LifecycleEventObserver { - override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { - if (event == Lifecycle.Event.ON_DESTROY) { - disposable.dispose() - lifecycle.removeObserver(this) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/iielse/imageviewer/demo/core/viewer/SimpleImageLoader.kt b/app/src/main/java/com/github/iielse/imageviewer/demo/core/viewer/SimpleImageLoader.kt index 806a276..102fb20 100644 --- a/app/src/main/java/com/github/iielse/imageviewer/demo/core/viewer/SimpleImageLoader.kt +++ b/app/src/main/java/com/github/iielse/imageviewer/demo/core/viewer/SimpleImageLoader.kt @@ -111,7 +111,7 @@ class SimpleImageLoader : ImageLoader { .doFinally { findLoadingView(viewHolder)?.visibility = View.GONE } .doOnNext { subsamplingView.setImage(ImageSource.uri(Uri.fromFile(it)).also { source -> subsamplingCache.put(url, source) }) } .doOnError { toast(it.message) } - .subscribe(ObserverAdapter(subsamplingView.lifecycleOwner?.lifecycle)) + .subscribe(ObserverAdapter(subsamplingView.lifecycleOwner.lifecycle)) } private fun subsamplingDownloadRequest(url: String): Observable { diff --git a/app/src/main/java/com/github/iielse/imageviewer/demo/utils/extensions.kt b/app/src/main/java/com/github/iielse/imageviewer/demo/utils/extensions.kt index 7ef1810..ddfb3a6 100644 --- a/app/src/main/java/com/github/iielse/imageviewer/demo/utils/extensions.kt +++ b/app/src/main/java/com/github/iielse/imageviewer/demo/utils/extensions.kt @@ -6,13 +6,9 @@ import android.content.ContextWrapper import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.collection.ArrayMap -import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.* import com.github.iielse.imageviewer.demo.R -import com.github.iielse.imageviewer.demo.core.LifecycleDisposable import io.reactivex.disposables.Disposable fun View.setOnClickCallback(interval: Long = 500L, callback: (View) -> Unit) { @@ -31,12 +27,11 @@ fun View.setOnClickCallback(interval: Long = 500L, callback: (View) -> Unit) { } fun Disposable.bindLifecycle(lifecycle: Lifecycle?) { - if (lifecycle == null) return - lifecycle.addObserver(LifecycleDisposable(lifecycle, this)) + lifecycle?.observeOnDestroy { dispose() } } -val View.activity: Activity? - get() = getActivity(context) +val View.activity: FragmentActivity? + get() = getActivity(context) as FragmentActivity? // https://stackoverflow.com/questions/9273218/is-it-always-safe-to-cast-context-to-activity-within-view/45364110 private fun getActivity(context: Context?): Activity? { @@ -46,51 +41,112 @@ private fun getActivity(context: Context?): Activity? { return null } -val View.lifecycleOwner: LifecycleOwner? get() { - val activity = activity as? FragmentActivity? ?: return null - val fragment = findSupportFragment(this, activity) - return fragment?.viewLifecycleOwner ?: activity -} -private val tempViewToSupportFragment = ArrayMap() -private fun findSupportFragment(target: View, activity: FragmentActivity): Fragment? { - tempViewToSupportFragment.clear() - findAllSupportFragmentsWithViews( - activity.supportFragmentManager.fragments, tempViewToSupportFragment - ) - var result: Fragment? = null - val activityRoot = activity.findViewById(android.R.id.content) - var current = target - while (current != activityRoot) { - result = tempViewToSupportFragment[current] - if (result != null) { - break - } - current = if (current.parent is View) { - current.parent as View - } else { - break +//val View.lifecycleOwner: LifecycleOwner? get() { +// val activity = activity as? FragmentActivity? ?: return null +// val fragment = findSupportFragment(this, activity) +// return fragment?.viewLifecycleOwner ?: activity +//} +//private val tempViewToSupportFragment = ArrayMap() +//private fun findSupportFragment(target: View, activity: FragmentActivity): Fragment? { +// tempViewToSupportFragment.clear() +// findAllSupportFragmentsWithViews( +// activity.supportFragmentManager.fragments, tempViewToSupportFragment +// ) +// var result: Fragment? = null +// val activityRoot = activity.findViewById(android.R.id.content) +// var current = target +// while (current != activityRoot) { +// result = tempViewToSupportFragment[current] +// if (result != null) { +// break +// } +// current = if (current.parent is View) { +// current.parent as View +// } else { +// break +// } +// } +// tempViewToSupportFragment.clear() +// return result +//} +// +//private fun findAllSupportFragmentsWithViews( +// topLevelFragments: Collection?, result: MutableMap +//) { +// if (topLevelFragments == null) { +// return +// } +// for (fragment in topLevelFragments) { +// // getFragment()s in the support FragmentManager may contain null values, see #1991. +// if (fragment?.view == null) { +// continue +// } +// result[fragment.view] = fragment +// findAllSupportFragmentsWithViews(fragment.childFragmentManager.fragments, result) +// } +//} + +val View.lifecycleOwner: LifecycleOwner get() { + val self = this + var owner = self.getTag(R.id.view_lifecycle_owner) as? LifecycleOwner? + if (owner == null) { + val lifecycleOwner = object : LifecycleOwner { + private val registry = LifecycleRegistry(this) + override fun getLifecycle() = registry } + self.setTag(R.id.view_lifecycle_owner, lifecycleOwner) + val viewLifecycle = lifecycleOwner.lifecycle + owner = lifecycleOwner + self.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View?) { + viewLifecycle.currentState = Lifecycle.State.CREATED + viewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START) + viewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) + } + + override fun onViewDetachedFromWindow(v: View?) { + viewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) + viewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP) + viewLifecycle.currentState = Lifecycle.State.DESTROYED + self.setTag(R.id.view_lifecycle_owner, null) + self.removeOnAttachStateChangeListener(this) + } + }) } - tempViewToSupportFragment.clear() - return result + return owner } -private fun findAllSupportFragmentsWithViews( - topLevelFragments: Collection?, result: MutableMap -) { - if (topLevelFragments == null) { - return - } - for (fragment in topLevelFragments) { - // getFragment()s in the support FragmentManager may contain null values, see #1991. - if (fragment?.view == null) { - continue +fun LiveData.observe(view: View, observer: Observer) { + this.observe(view.lifecycleOwner, observer) +} + +fun Lifecycle.observeOnDestroy(block: () -> Unit) { + val self = this + self.addObserver(object : LifecycleEventObserver { + override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { + if (event == Lifecycle.Event.ON_DESTROY) { + block() + self.removeObserver(this) + } } - result[fragment.view] = fragment - findAllSupportFragmentsWithViews(fragment.childFragmentManager.fragments, result) - } + }) } +fun Lifecycle.observeOnResume(once: Boolean = true, block: () -> Unit) { + val self = this + self.addObserver(object : LifecycleEventObserver { + override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { + if (event == Lifecycle.Event.ON_RESUME) { + block() + if (once) self.removeObserver(this) + } else if (event == Lifecycle.Event.ON_DESTROY) { + self.removeObserver(this) + } + } + }) +} + + fun ViewGroup.inflate(resId: Int): View { return LayoutInflater.from(context).inflate(resId, this, false) } diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 36d9cb2..d1717b0 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -1,4 +1,6 @@ + + \ No newline at end of file