Skip to content

Commit

Permalink
opt demo code
Browse files Browse the repository at this point in the history
  • Loading branch information
iielse committed Sep 7, 2022
1 parent 61ea304 commit 9dcc5bc
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -133,19 +133,18 @@ class SimpleViewerCustomizer : LifecycleEventObserver, VHCustomizer, OverlayCust

private fun processSelectVideo(viewHolder: RecyclerView.ViewHolder) {
videoTask?.dispose()
lastVideoVH?.itemView?.findViewById<ExoVideoView>(R.id.videoView)?.reset()
lastVideoVH?.binding?.videoView?.reset()

when (viewHolder) {
is VideoViewHolder -> {
val videoView = viewHolder.itemView.findViewById<ExoVideoView>(R.id.videoView)

val task = object : ObserverAdapter<Long>(videoView?.lifecycleOwner?.lifecycle) {
val videoView = viewHolder.binding.videoView
val task = object : ObserverAdapter<Long>(videoView.lifecycleOwner.lifecycle) {
override fun onNext(t: Long) {
if (ViewerHelper.simplePlayVideo) {
videoView?.resume()
videoView.resume()
} else {
val playerControlView = viewHolder.itemView.findViewById<PlayerControlView>(R.id.playerControlView)
playerControlView?.player = videoView?.player()
playerControlView?.player = videoView.player()
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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<File> {
Expand Down
150 changes: 103 additions & 47 deletions app/src/main/java/com/github/iielse/imageviewer/demo/utils/extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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? {
Expand All @@ -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<View, Fragment>()
private fun findSupportFragment(target: View, activity: FragmentActivity): Fragment? {
tempViewToSupportFragment.clear()
findAllSupportFragmentsWithViews(
activity.supportFragmentManager.fragments, tempViewToSupportFragment
)
var result: Fragment? = null
val activityRoot = activity.findViewById<View>(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<View, Fragment>()
//private fun findSupportFragment(target: View, activity: FragmentActivity): Fragment? {
// tempViewToSupportFragment.clear()
// findAllSupportFragmentsWithViews(
// activity.supportFragmentManager.fragments, tempViewToSupportFragment
// )
// var result: Fragment? = null
// val activityRoot = activity.findViewById<View>(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<Fragment?>?, result: MutableMap<View?, Fragment>
//) {
// 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<Fragment?>?, result: MutableMap<View?, Fragment>
) {
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 <T> LiveData<T>.observe(view: View, observer: Observer<T>) {
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)
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/ids.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="view_last_click_timestamp" type="id" />

<item name="view_lifecycle_owner" type="id" />
</resources>

0 comments on commit 9dcc5bc

Please sign in to comment.