private static boolean isAttachedToWindow(RecyclerView hostView) { if (Build.VERSION.SDK_INT >= 19) { return hostView.isAttachedToWindow(); } else { return (hostView.getHandler() != null); } }
private static boolean isAttachedToWindow(RecyclerView hostView) { if (Build.VERSION.SDK_INT >= 19) { return hostView.isAttachedToWindow(); } else { return (hostView.getHandler() != null); } }
|| !mMountedView.isAttachedToWindow() || !isVisibleToUser(mMountedView)) { final boolean isMounted = (mMountedView != null); .append(mMountedView.hasPendingAdapterUpdates()) .append(", isAttachedToWindow(): ") .append(mMountedView.isAttachedToWindow()) .append(", getWindowVisibility(): ") .append(mMountedView.getWindowVisibility())
@Test public void testDataRenderedCallbacksAreNotTriggered() { final ChangeSetCompleteCallback changeSetCompleteCallback = mock(ChangeSetCompleteCallback.class); final ComponentsLogger componentsLogger = mock(ComponentsLogger.class); final ComponentContext componentContext = new ComponentContext(RuntimeEnvironment.application, "", componentsLogger); final RecyclerBinder recyclerBinder = new RecyclerBinder.Builder().rangeRatio(RANGE_RATIO).build(componentContext); for (int i = 0; i < 40; i++) { recyclerBinder.notifyChangeSetComplete(true, changeSetCompleteCallback); } final RecyclerView recyclerView = mock(LithoRecylerView.class); when(recyclerView.hasPendingAdapterUpdates()).thenReturn(true); when(recyclerView.isAttachedToWindow()).thenReturn(true); when(recyclerView.getWindowVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getAlpha()).thenReturn(1f); when(recyclerView.getVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getGlobalVisibleRect(any(Rect.class))).thenReturn(true); recyclerBinder.mount(recyclerView); recyclerBinder.notifyChangeSetComplete(true, changeSetCompleteCallback); verify(componentsLogger).emitMessage(eq(ComponentsLogger.LogLevel.ERROR), anyString()); assertThat(recyclerBinder.mDataRenderedCallbacks).isEmpty(); }
@Test public void testOnDataRenderedWithViewVisibilityIsGone() { final ChangeSetCompleteCallback changeSetCompleteCallback = mock(ChangeSetCompleteCallback.class); final RecyclerBinder recyclerBinder = new RecyclerBinder.Builder().rangeRatio(RANGE_RATIO).build(mComponentContext); final ArrayList<RenderInfo> renderInfos = new ArrayList<>(); for (int i = 0; i < 5; i++) { final Component component = TestDrawableComponent.create(mComponentContext).widthPx(100).heightPx(100).build(); renderInfos.add(ComponentRenderInfo.create().component(component).build()); } final RecyclerView recyclerView = mock(LithoRecylerView.class); when(recyclerView.hasPendingAdapterUpdates()).thenReturn(true); when(recyclerView.isAttachedToWindow()).thenReturn(true); when(recyclerView.getWindowVisibility()).thenReturn(View.GONE); when(recyclerView.getAlpha()).thenReturn(1f); when(recyclerView.getVisibility()).thenReturn(View.GONE); when(recyclerView.getGlobalVisibleRect(any(Rect.class))).thenReturn(false); recyclerBinder.mount(recyclerView); recyclerBinder.insertRangeAt(0, renderInfos); recyclerBinder.notifyChangeSetComplete(true, changeSetCompleteCallback); verify(changeSetCompleteCallback).onDataRendered(eq(true), anyLong()); }
@Test public void testOnDataRenderedWithNoPendingUpdate() { final ChangeSetCompleteCallback changeSetCompleteCallback = mock(ChangeSetCompleteCallback.class); final RecyclerBinder recyclerBinder = new RecyclerBinder.Builder().rangeRatio(RANGE_RATIO).build(mComponentContext); final ArrayList<RenderInfo> renderInfos = new ArrayList<>(); for (int i = 0; i < 5; i++) { final Component component = TestDrawableComponent.create(mComponentContext).widthPx(100).heightPx(100).build(); renderInfos.add(ComponentRenderInfo.create().component(component).build()); } final RecyclerView recyclerView = mock(LithoRecylerView.class); when(recyclerView.hasPendingAdapterUpdates()).thenReturn(false); when(recyclerView.isAttachedToWindow()).thenReturn(true); when(recyclerView.getWindowVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getAlpha()).thenReturn(1f); when(recyclerView.getVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getGlobalVisibleRect(any(Rect.class))).thenReturn(true); recyclerBinder.mount(recyclerView); recyclerBinder.insertRangeAt(0, renderInfos); recyclerBinder.notifyChangeSetComplete(true, changeSetCompleteCallback); verify(changeSetCompleteCallback).onDataRendered(eq(true), anyLong()); }
@Test public void testOnDataRenderedWithViewDetachedFromWindow() { final ChangeSetCompleteCallback changeSetCompleteCallback = mock(ChangeSetCompleteCallback.class); final RecyclerBinder recyclerBinder = new RecyclerBinder.Builder().rangeRatio(RANGE_RATIO).build(mComponentContext); final ArrayList<RenderInfo> renderInfos = new ArrayList<>(); for (int i = 0; i < 5; i++) { final Component component = TestDrawableComponent.create(mComponentContext).widthPx(100).heightPx(100).build(); renderInfos.add(ComponentRenderInfo.create().component(component).build()); } final RecyclerView recyclerView = mock(LithoRecylerView.class); when(recyclerView.hasPendingAdapterUpdates()).thenReturn(true); when(recyclerView.isAttachedToWindow()).thenReturn(false); when(recyclerView.getWindowVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getAlpha()).thenReturn(1f); when(recyclerView.getVisibility()).thenReturn(View.VISIBLE); when(recyclerView.getGlobalVisibleRect(any(Rect.class))).thenReturn(true); recyclerBinder.mount(recyclerView); recyclerBinder.insertRangeAt(0, renderInfos); recyclerBinder.notifyChangeSetComplete(true, changeSetCompleteCallback); verify(changeSetCompleteCallback).onDataRendered(eq(true), anyLong()); }
@Override public void run() { if (mMountedView == null || !mMountedView.hasPendingAdapterUpdates()) { if (mViewportManager.shouldUpdate()) { mViewportManager.onViewportChanged(State.DATA_CHANGES); } mPostUpdateViewportAttempts = 0; return; } // If the view gets detached, we might still have pending updates. // If the view's visibility is GONE, layout won't happen until it becomes visible. We have // to exit here, otherwise we keep posting this runnable to the next frame until it // becomes visible. if (!mMountedView.isAttachedToWindow() || mMountedView.getVisibility() == View.GONE) { mPostUpdateViewportAttempts = 0; return; } if (mPostUpdateViewportAttempts >= POST_UPDATE_VIEWPORT_AND_COMPUTE_RANGE_MAX_ATTEMPTS) { mPostUpdateViewportAttempts = 0; if (mViewportManager.shouldUpdate()) { mViewportManager.onViewportChanged(State.DATA_CHANGES); } return; } // If we have pending updates, wait until the sync operations are finished and try again // in the next frame. mPostUpdateViewportAttempts++; ViewCompat.postOnAnimation(mMountedView, mUpdateViewportRunnable); } };
private boolean isAttachedToWindow(RecyclerView hostView) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return hostView.isAttachedToWindow(); } else { return (hostView.getHandler() != null); } }
private boolean isAttachedToWindow(RecyclerView hostView) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return hostView.isAttachedToWindow(); } else { return (hostView.getHandler() != null); } }
/** */ @Override @SuppressWarnings("NewApi") public boolean isAttachedToWindow() { this.ensureDecorator(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) return super.isAttachedToWindow(); else return mDecorator.hasPrivateFlag(PrivateFlags.PFLAG_ATTACHED_TO_WINDOW); }
/** */ @Override @SuppressWarnings("NewApi") public boolean isAttachedToWindow() { this.ensureDecorator(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) return super.isAttachedToWindow(); else return mDecorator.hasPrivateFlag(PrivateFlags.PFLAG_ATTACHED_TO_WINDOW); }
data.put("HasPendingAdapterUpdates", rv.hasPendingAdapterUpdates()); data.put("IsAnimating", rv.isAnimating()); data.put("IsAttachedToWindow", rv.isAttachedToWindow()); data.put("IsComputingLayout", rv.isComputingLayout()); data.put("IsLayoutFrozen", rv.isLayoutFrozen());