Skip to content

Commit

Permalink
fix(android): to use WeakReference as much as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
siguangli2018 committed Jul 12, 2024
1 parent 3849133 commit a35a34d
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.views.custom.HippyCustomPropsController;
import com.tencent.mtt.hippy.views.hippylist.HippyRecyclerViewController;
import com.tencent.mtt.hippy.views.hippylist.HippyRecyclerViewWrapper;
import com.tencent.mtt.hippy.views.image.HippyImageViewController;
import com.tencent.mtt.hippy.views.list.HippyListItemViewController;
import com.tencent.mtt.hippy.views.modal.HippyModalHostManager;
Expand All @@ -58,6 +57,7 @@
import com.tencent.renderer.Renderer;
import com.tencent.renderer.node.RenderNode;
import com.tencent.renderer.node.VirtualNode;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand All @@ -74,24 +74,26 @@ public class ControllerManager {
@NonNull
private final Map<Integer, Pool<String, View>> mRecycleViewPools = new HashMap<>();
@Nullable
private Renderer mRenderer;
private final WeakReference<Renderer> mRendererWeakRef;
@Nullable
private static List<Class<?>> sDefaultControllers;

public ControllerManager(@NonNull Renderer renderer) {
mRenderer = renderer;
mRendererWeakRef = new WeakReference<>(renderer);
mControllerRegistry = new ControllerRegistry(renderer);
mControllerUpdateManger = new ControllerUpdateManger<>(renderer);
}

@Nullable
public RenderManager getRenderManager() {
return mRenderer != null ? ((NativeRender) mRenderer).getRenderManager() : null;
Renderer renderer = mRendererWeakRef.get();
return renderer != null ? ((NativeRender) renderer).getRenderManager() : null;
}

@Nullable
public NativeRender getNativeRender() {
return mRenderer != null ? ((NativeRender) mRenderer) : null;
Renderer renderer = mRendererWeakRef.get();
return renderer != null ? ((NativeRender) renderer) : null;
}

@NonNull
Expand Down Expand Up @@ -192,7 +194,6 @@ public void destroy() {
deleteRootView(mControllerRegistry.getRootIdAt(i));
}
}
mRenderer = null;
}

@Nullable
Expand Down Expand Up @@ -234,7 +235,7 @@ public void preCreateView(int rootId, int id, @NonNull String className,
if (view != null || rootView == null || controller == null) {
return;
}
view = controller.createView(rootView, id, mRenderer, className, props);
view = controller.createView(rootView, id, mRendererWeakRef.get(), className, props);
if (view != null) {
addPreView(view, rootId);
}
Expand Down Expand Up @@ -291,7 +292,7 @@ public View createView(@NonNull RenderNode node, PoolType cachePoolType) {
if (controller == null) {
return null;
}
view = controller.createView(rootView, id, mRenderer, className, node.getProps());
view = controller.createView(rootView, id, mRendererWeakRef.get(), className, node.getProps());
node.setNodeFlag(FLAG_UPDATE_LAYOUT);
}
if (view != null) {
Expand Down Expand Up @@ -625,21 +626,23 @@ private String getViewOperationExceptionMessage(int pid, View parent, int id, Vi
}

private void reportRemoveViewException(int pid, View parent, int id, View child) {
if (mRenderer != null) {
Renderer renderer = mRendererWeakRef.get();
if (renderer != null) {
NativeRenderException exception = new NativeRenderException(
REMOVE_CHILD_VIEW_FAILED_ERR,
getViewOperationExceptionMessage(pid, parent, id, child,
"Remove view failed:"));
mRenderer.handleRenderException(exception);
renderer.handleRenderException(exception);
}
}

private void reportAddViewException(int pid, View parent, int id, View child) {
if (mRenderer != null) {
Renderer renderer = mRendererWeakRef.get();
if (renderer != null) {
NativeRenderException exception = new NativeRenderException(ADD_CHILD_VIEW_FAILED_ERR,
getViewOperationExceptionMessage(pid, parent, id, child,
"Add child to parent failed:"));
mRenderer.handleRenderException(exception);
renderer.handleRenderException(exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.tencent.renderer.Renderer;
import com.tencent.renderer.node.RenderNode;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -42,15 +43,13 @@ public class ControllerRegistry {
@NonNull
private final Map<String, ControllerHolder> mControllers = new HashMap<>();
@Nullable
private Renderer mRenderer;
private final WeakReference<Renderer> mRendererWeakRef;

public ControllerRegistry(@NonNull Renderer renderer) {
mRenderer = renderer;
mRendererWeakRef = new WeakReference<>(renderer);
}

public void clear() {
mRenderer = null;
}
public void clear() {}

public void addControllerHolder(String name, ControllerHolder controllerHolder) {
mControllers.put(name, controllerHolder);
Expand All @@ -66,10 +65,11 @@ public ControllerHolder getControllerHolder(String className) {
public HippyViewController getViewController(@NonNull String className) {
ControllerHolder holder = mControllers.get(className);
if (holder == null) {
if (mRenderer != null) {
Renderer renderer = mRendererWeakRef.get();
if (renderer != null) {
NativeRenderException exception = new NativeRenderException(
GET_VIEW_CONTROLLER_FAILED_ERR, "Unknown class name=" + className);
mRenderer.handleRenderException(exception);
renderer.handleRenderException(exception);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.tencent.renderer.utils.PropertyUtils.PropertyMethodHolder;
import com.tencent.renderer.node.RenderNode;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -64,7 +65,7 @@ public class ControllerUpdateManger<T> {
NodeProps.OVERFLOW
};
@Nullable
private Renderer mRenderer;
private final WeakReference<Renderer> mRendererWeakRef;
@Nullable
private ComponentController mComponentController;
@Nullable
Expand All @@ -79,11 +80,11 @@ public class ControllerUpdateManger<T> {
}

public ControllerUpdateManger(@NonNull Renderer renderer) {
mRenderer = renderer;
mRendererWeakRef = new WeakReference<>(renderer);
}

public void clear() {
mRenderer = null;

}

public void setCustomPropsController(T controller) {
Expand Down Expand Up @@ -144,10 +145,7 @@ private static boolean isComponentProps(String name) {
return true;
}
// Special case: property "opacity" in TextVirtualNode also need to process in HippyViewController
if (NodeProps.OPACITY.equals(name)) {
return true;
}
return false;
return NodeProps.OPACITY.equals(name);
}

void findViewPropsMethod(Class<?> cls,
Expand Down Expand Up @@ -198,8 +196,9 @@ private void invokePropMethod(@NonNull Object obj, @NonNull Object arg1,
methodHolder.method.invoke(obj, arg1, value);
}
} catch (Exception exception) {
if (mRenderer != null) {
mRenderer.handleRenderException(
Renderer renderer = mRendererWeakRef.get();
if (renderer != null) {
renderer.handleRenderException(
PropertyUtils.makePropertyConvertException(exception, key,
methodHolder.method));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ protected void init() {
public void onDestroy() {
if (stickyHeaderHelper != null) {
stickyHeaderHelper.detachSticky();
stickyHeaderHelper.onDestroy();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ public class StickyHeaderHelper extends OnScrollListener implements

private static final String TAG = "StickyHeaderHelper";
private static final int INVALID_POSITION = -1;
private final com.tencent.mtt.hippy.views.hippylist.recyclerview.helper.skikcy.IHeaderAttachListener headerAttachListener;
private IHeaderAttachListener headerAttachListener;
private RecyclerViewBase recyclerView;
private com.tencent.mtt.hippy.views.hippylist.recyclerview.helper.skikcy.IStickyItemsProvider stickyItemsProvider;
private StickyViewFactory stickyViewFactory;
private IHeaderHost headerHost;
private IStickyItemsProvider stickyItemsProvider;
private final StickyViewFactory stickyViewFactory;
private ViewHolder headerOrgViewHolder;
private boolean orgViewHolderCanRecyclable = false;
private View currentHeaderView;
private int orientation;
private int currentStickPos = -1;
private com.tencent.mtt.hippy.views.hippylist.recyclerview.helper.skikcy.IHeaderHost headerHost;
private com.tencent.mtt.hippy.views.hippylist.recyclerview.helper.skikcy.StickViewListener stickViewListener;
private boolean isUpdateStickyHolderWhenLayout;

Expand All @@ -59,9 +59,9 @@ public StickyHeaderHelper(final RecyclerViewBase recyclerView,
IHeaderAttachListener headerAttachListener, IHeaderHost headerHost) {
this.recyclerView = recyclerView;
this.headerAttachListener = headerAttachListener;
this.headerHost = headerHost;
this.stickyItemsProvider = stickyItemsProvider;
stickyViewFactory = new StickyViewFactory(recyclerView);
this.headerHost = headerHost;
orientation = recyclerView.getLayoutManager().canScrollVertically() ? VERTICAL : HORIZONTAL;
}

Expand Down Expand Up @@ -94,6 +94,14 @@ public void setUpdateStickyViewWhenLayout(boolean bindStickyHolderWhenLayout) {
isUpdateStickyHolderWhenLayout = bindStickyHolderWhenLayout;
}

public void onDestroy() {
recyclerView = null;
headerAttachListener = null;
headerHost = null;
stickyItemsProvider = null;
currentHeaderView = null;
}

/**
* 如果当前stickHolder和新的stickyHolder 不一样,那么把当前的stickyHolder删除掉,并还原HeaderView的Translation
*/
Expand All @@ -103,7 +111,9 @@ public void detachSticky() {
currentHeaderView.setTranslationY(0);
currentHeaderView.setTranslationX(0);
returnHeaderBackToList();
headerHost.removeOnLayoutListener(this);
if (headerHost != null) {
headerHost.removeOnLayoutListener(this);
}
notifyStickDetached();
}
currentStickPos = -1;
Expand All @@ -123,16 +133,16 @@ private void notifyStickDetached() {
*/
private void returnHeaderBackToList() {
headerOrgViewHolder.setIsRecyclable(orgViewHolderCanRecyclable);
if (headerAttachListener != null) {
if (headerAttachListener != null && currentHeaderView != null) {
headerAttachListener.onHeaderDetached(headerOrgViewHolder, currentHeaderView);
} else {
} else if (recyclerView != null) {
ViewHolder viewHolderToReturn = recyclerView
.findViewHolderForAdapterPosition(headerOrgViewHolder.getAdapterPosition());
if (viewHolderToReturn != null && viewHolderToReturn.itemView instanceof ViewGroup) {
ViewGroup itemView = (ViewGroup) viewHolderToReturn.itemView;
//已经有孩子了,就不要加了,这个可能是新创建的ViewHolder已经有了内容
if (itemView.getChildCount() <= 0) {
itemView.addView(this.currentHeaderView);
if (itemView.getChildCount() <= 0 && currentHeaderView != null) {
itemView.addView(currentHeaderView);
}
}
}
Expand All @@ -142,7 +152,7 @@ private void returnHeaderBackToList() {
* 将stickyItemPosition对应的View挂载到RecyclerView的父亲上面
*/
private void attachSticky(int newStickyPosition) {
if (newStickyPosition != INVALID_POSITION) {
if (newStickyPosition != INVALID_POSITION && headerHost != null) {
headerOrgViewHolder = stickyViewFactory.getHeaderForPosition(newStickyPosition);
currentStickPos = newStickyPosition;
Log.d("returnHeader", "attachSticky:" + headerOrgViewHolder);
Expand Down Expand Up @@ -172,7 +182,7 @@ private void notifyStickAttached(int stickyPosition) {
* 设置吸顶的View的偏移 在下一个吸顶view和当前吸顶的view交汇的时候,需要把当前吸顶view往上面移动,慢慢会把当前的吸顶view顶出屏幕
*/
private void offsetSticky() {
if (headerOrgViewHolder != null) {
if (headerOrgViewHolder != null && currentHeaderView != null) {
float offset = getOffset(findNextSticky(currentStickPos));
if (orientation == VERTICAL) {
currentHeaderView.setTranslationY(offset);
Expand All @@ -186,6 +196,9 @@ private void offsetSticky() {
* 找到屏幕中,下一个即将吸顶的view,主要用于计算当前吸顶的HeaderView的Offset, 下一个即将吸顶的View会慢慢把当前正在吸顶的HeaderView慢慢顶出屏幕外
*/
private View findNextSticky(int currentStickyPos) {
if (recyclerView == null || stickyItemsProvider == null) {
return null;
}
for (int i = 0; i < recyclerView.getChildCount(); i++) {
View nextStickyView = recyclerView.getChildAt(i);
int nextStickyPos = recyclerView.getChildLayoutPosition(nextStickyView);
Expand Down Expand Up @@ -239,7 +252,7 @@ public void onGlobalLayout() {
* @return INVALID_POSITION,没有找到stickyItem
*/
public int getStickyItemPosition() {
if (recyclerView.getChildCount() <= 0) {
if (recyclerView == null || stickyItemsProvider == null || recyclerView.getChildCount() <= 0) {
return INVALID_POSITION;
}
int positionToSticky = INVALID_POSITION;
Expand Down Expand Up @@ -285,7 +298,7 @@ private void removeViewFromParent(View view) {
}

private void updateStickHolder() {
if (headerOrgViewHolder != null) {
if (headerOrgViewHolder != null && recyclerView != null) {
recyclerView.getAdapter().onBindViewHolder(headerOrgViewHolder, currentStickPos);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@

import androidx.recyclerview.widget.RecyclerViewBase;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import java.lang.ref.WeakReference;

public final class StickyViewFactory implements IHeaderViewFactory {

private final RecyclerViewBase recyclerView;
private final WeakReference<RecyclerViewBase> recyclerViewWeakRef;

public StickyViewFactory(RecyclerViewBase recyclerView) {
this.recyclerView = recyclerView;
recyclerViewWeakRef = new WeakReference<>(recyclerView);
}

/**
Expand All @@ -37,7 +38,8 @@ public StickyViewFactory(RecyclerViewBase recyclerView) {
* @return 返回对应到ViewHolder,不会返回Null
*/
public ViewHolder getHeaderForPosition(int position) {
if (position < 0) {
RecyclerViewBase recyclerView = recyclerViewWeakRef.get();
if (position < 0 || recyclerView == null) {
return null;
}
ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
Expand Down
Loading

0 comments on commit a35a34d

Please sign in to comment.