-
Notifications
You must be signed in to change notification settings - Fork 728
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable recycling of views within groups (#657)
* Enable recycling of views within groups * cleanup * revert to kotlin 1.2.71 * fix test
- Loading branch information
Showing
12 changed files
with
655 additions
and
409 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
epoxy-adapter/src/main/java/com/airbnb/epoxy/ActivityRecyclerPool.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package com.airbnb.epoxy | ||
|
||
import android.app.Activity | ||
import android.content.Context | ||
import android.os.Build | ||
import androidx.core.view.ViewCompat | ||
import androidx.lifecycle.Lifecycle | ||
import androidx.lifecycle.LifecycleObserver | ||
import androidx.lifecycle.LifecycleOwner | ||
import androidx.lifecycle.OnLifecycleEvent | ||
import androidx.recyclerview.widget.RecyclerView | ||
import java.lang.ref.WeakReference | ||
import java.util.ArrayList | ||
|
||
internal class ActivityRecyclerPool { | ||
|
||
/** | ||
* Store one unique pool per activity. They are cleared out when activities are destroyed, so this | ||
* only needs to hold pools for active activities. | ||
*/ | ||
private val pools = ArrayList<PoolReference>(5) | ||
|
||
@JvmOverloads | ||
fun getPool( | ||
context: Context, | ||
poolFactory: () -> RecyclerView.RecycledViewPool = { UnboundedViewPool() } | ||
): PoolReference { | ||
|
||
val iterator = pools.iterator() | ||
var poolToUse: PoolReference? = null | ||
|
||
while (iterator.hasNext()) { | ||
val poolReference = iterator.next() | ||
when { | ||
poolReference.context === context -> { | ||
if (poolToUse != null) { | ||
throw IllegalStateException("A pool was already found") | ||
} | ||
poolToUse = poolReference | ||
// finish iterating to remove any old contexts | ||
} | ||
poolReference.context.isActivityDestroyed() -> { | ||
// A pool from a different activity that was destroyed. | ||
// Clear the pool references to allow the activity to be GC'd | ||
poolReference.viewPool.clear() | ||
iterator.remove() | ||
} | ||
} | ||
} | ||
|
||
if (poolToUse == null) { | ||
poolToUse = PoolReference(context, poolFactory(), this) | ||
(context as? LifecycleOwner)?.lifecycle?.addObserver(poolToUse) | ||
pools.add(poolToUse) | ||
} | ||
|
||
return poolToUse | ||
} | ||
|
||
fun clearIfDestroyed(pool: PoolReference) { | ||
if (pool.context.isActivityDestroyed()) { | ||
pool.viewPool.clear() | ||
pools.remove(pool) | ||
} | ||
} | ||
} | ||
|
||
internal class PoolReference( | ||
context: Context, | ||
val viewPool: RecyclerView.RecycledViewPool, | ||
private val parent: ActivityRecyclerPool | ||
) : LifecycleObserver { | ||
private val contextReference: WeakReference<Context> = WeakReference(context) | ||
|
||
val context: Context? get() = contextReference.get() | ||
|
||
fun clearIfDestroyed() { | ||
parent.clearIfDestroyed(this) | ||
} | ||
|
||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) | ||
fun onContextDestroyed() { | ||
clearIfDestroyed() | ||
} | ||
} | ||
|
||
internal fun Context?.isActivityDestroyed(): Boolean { | ||
if (this == null) { | ||
return true | ||
} | ||
|
||
if (this !is Activity) { | ||
return false | ||
} | ||
|
||
if (isFinishing) { | ||
return true | ||
} | ||
|
||
return if (Build.VERSION.SDK_INT >= 17) { | ||
isDestroyed | ||
} else { | ||
// Use this as a proxy for being destroyed on older devices | ||
!ViewCompat.isAttachedToWindow(window.decorView) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.