Drastically reduce number of projection instances we create.

Via SimplePool
This commit is contained in:
Alex Hart
2021-10-25 14:12:08 -03:00
committed by GitHub
parent 98fce53cf1
commit b34bb2e7d7
12 changed files with 145 additions and 64 deletions

View File

@@ -9,6 +9,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pools;
import androidx.recyclerview.widget.RecyclerView;
import org.signal.core.util.logging.Log;
@@ -24,30 +25,41 @@ import java.util.Objects;
*/
public final class Projection {
private final float x;
private final float y;
private final int width;
private final int height;
private final Corners corners;
private final Path path;
private final RectF rect;
private float x;
private float y;
private int width;
private int height;
private Corners corners;
private Path path;
private RectF rect;
public Projection(float x, float y, int width, int height, @Nullable Corners corners) {
private Projection() {
x = 0f;
y = 0f;
width = 0;
height = 0;
corners = null;
path = new Path();
rect = new RectF();
}
private Projection set(float x, float y, int width, int height, @Nullable Corners corners) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.corners = corners;
this.path = new Path();
rect = new RectF();
rect.set(x, y, x + width, y + height);
path.reset();
if (corners != null) {
path.addRoundRect(rect, corners.toRadii(), Path.Direction.CW);
} else {
path.addRect(rect, Path.Direction.CW);
}
return this;
}
public float getX() {
@@ -86,35 +98,12 @@ public final class Projection {
}
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Projection that = (Projection) o;
return Float.compare(that.x, x) == 0 &&
Float.compare(that.y, y) == 0 &&
width == that.width &&
height == that.height &&
Objects.equals(corners, that.corners);
}
@Override public int hashCode() {
return Objects.hash(x, y, width, height, corners);
}
public @NonNull Projection translateX(float xTranslation) {
return new Projection(x + xTranslation, y, width, height, corners);
return set(x + xTranslation, y, width, height, corners);
}
public @NonNull Projection translateY(float yTranslation) {
return new Projection(x, y + yTranslation, width, height, corners);
}
public @NonNull Projection withDimensions(int width, int height) {
return new Projection(x, y, width, height, corners);
}
public @NonNull Projection withHeight(int height) {
return new Projection(x, y, width, height, corners);
return set(x, y + yTranslation, width, height, corners);
}
public static @NonNull Projection relativeToParent(@NonNull ViewGroup parent, @NonNull View view, @Nullable Corners corners) {
@@ -122,7 +111,7 @@ public final class Projection {
view.getDrawingRect(viewBounds);
parent.offsetDescendantRectToMyCoords(view, viewBounds);
return new Projection(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners);
return acquireAndSet(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners);
}
public static @NonNull Projection relativeToViewRoot(@NonNull View view, @Nullable Corners corners) {
@@ -132,7 +121,7 @@ public final class Projection {
view.getDrawingRect(viewBounds);
root.offsetDescendantRectToMyCoords(view, viewBounds);
return new Projection(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners);
return acquireAndSet(viewBounds.left, viewBounds.top, view.getWidth(), view.getHeight(), corners);
}
public static @NonNull Projection relativeToViewWithCommonRoot(@NonNull View toProject, @NonNull View viewWithCommonRoot, @Nullable Corners corners) {
@@ -143,7 +132,7 @@ public final class Projection {
root.offsetDescendantRectToMyCoords(toProject, viewBounds);
root.offsetRectIntoDescendantCoords(viewWithCommonRoot, viewBounds);
return new Projection(viewBounds.left, viewBounds.top, toProject.getWidth(), toProject.getHeight(), corners);
return acquireAndSet(viewBounds.left, viewBounds.top, toProject.getWidth(), toProject.getHeight(), corners);
}
public static @NonNull Projection translateFromDescendantToParentCoords(@NonNull Projection descendantProjection, @NonNull View descendant, @NonNull ViewGroup parent) {
@@ -153,7 +142,7 @@ public final class Projection {
parent.offsetDescendantRectToMyCoords(descendant, viewBounds);
return new Projection(viewBounds.left, viewBounds.top, descendantProjection.width, descendantProjection.height, descendantProjection.corners);
return acquireAndSet(viewBounds.left, viewBounds.top, descendantProjection.width, descendantProjection.height, descendantProjection.corners);
}
public static @NonNull List<Projection> getCapAndTail(@NonNull Projection parentProjection, @NonNull Projection childProjection) {
@@ -187,11 +176,47 @@ public final class Projection {
}
return Arrays.asList(
new Projection(topX, topY, topWidth, topHeight, topCorners),
new Projection(bottomX, bottomY, bottomWidth, bottomHeight, bottomCorners)
acquireAndSet(topX, topY, topWidth, topHeight, topCorners),
acquireAndSet(bottomX, bottomY, bottomWidth, bottomHeight, bottomCorners)
);
}
/**
* We keep a maximum of 125 Projections around at any one time.
*/
private static final Pools.SimplePool<Projection> projectionPool = new Pools.SimplePool<>(125);
/**
* Acquire a projection. This will try to grab one from the pool, and, upon failure, will
* allocate a new one instead.
*/
private static @NonNull Projection acquire() {
Projection fromPool = projectionPool.acquire();
if (fromPool != null) {
return fromPool;
} else {
return new Projection();
}
}
/**
* Acquire a projection and set its fields as specified.
*/
private static @NonNull Projection acquireAndSet(float x, float y, int width, int height, @Nullable Corners corners) {
Projection projection = acquire();
projection.set(x, y, width, height, corners);
return projection;
}
/**
* Projections should only be kept around for the absolute maximum amount of time they are needed.
*/
public void release() {
projectionPool.release(this);
}
public static final class Corners {
private final float topLeft;
private final float topRight;

View File

@@ -0,0 +1,9 @@
package org.thoughtcrime.securesms.util
import java.io.Closeable
class ProjectionList(size: Int = 0) : ArrayList<Projection>(size), Closeable {
override fun close() {
forEach { it.release() }
}
}