Merge "Separate inflate from render step" into nyc-dev

This commit is contained in:
Diego Perez
2016-04-05 08:17:45 +00:00
committed by Android (Google) Code Review
5 changed files with 61 additions and 27 deletions

View File

@@ -24,6 +24,7 @@ import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderDrawable;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
import com.android.layoutlib.bridge.util.DynamicIdMap;
@@ -408,7 +409,9 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
/**
* Starts a layout session by inflating and rendering it. The method returns a
* {@link RenderSession} on which further actions can be taken.
*
* <p/>
* If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
* this method will only inflate the layout but will NOT render it.
* @param params the {@link SessionParams} object with all the information necessary to create
* the scene.
* @return a new {@link RenderSession} object that contains the result of the layout.
@@ -424,7 +427,10 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
lastResult = scene.init(params.getTimeout());
if (lastResult.isSuccess()) {
lastResult = scene.inflate();
if (lastResult.isSuccess()) {
boolean doNotRenderOnCreate = Boolean.TRUE.equals(
params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
if (lastResult.isSuccess() && !doNotRenderOnCreate) {
lastResult = scene.render(true /*freshRender*/);
}
}

View File

@@ -53,6 +53,12 @@ public final class RenderParamsFlags {
*/
public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
new Key<Boolean>("xmlFileParser", Boolean.class);
/**
* To tell LayoutLib to not render when creating a new session. This allows controlling when the first
* layout rendering will happen.
*/
public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
// Disallow instances.
private RenderParamsFlags() {}

View File

@@ -266,6 +266,34 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
mElapsedFrameTimeNanos = nanos;
}
/**
* Renders the given view hierarchy to the passed canvas and returns the result of the render
* operation.
* @param canvas an optional canvas to render the views to. If null, only the measure and
* layout steps will be executed.
*/
private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
@Nullable Canvas canvas, int width, int height) {
// measure again with the size we need
// This must always be done before the call to layout
measureView(viewRoot, null /*measuredView*/,
width, MeasureSpec.EXACTLY,
height, MeasureSpec.EXACTLY);
// now do the layout.
viewRoot.layout(0, 0, width, height);
handleScrolling(context, viewRoot);
if (canvas == null) {
return SUCCESS.createResult();
}
AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
viewRoot.draw(canvas);
return SUCCESS.createResult();
}
/**
* Renders the scene.
* <p>
@@ -367,24 +395,12 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
// measure again with the size we need
// This must always be done before the call to layout
measureView(mViewRoot, null /*measuredView*/,
mMeasuredScreenWidth, MeasureSpec.EXACTLY,
mMeasuredScreenHeight, MeasureSpec.EXACTLY);
// now do the layout.
mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
handleScrolling(mViewRoot);
Result renderResult = SUCCESS.createResult();
if (params.isLayoutOnly()) {
// delete the canvas and image to reset them on the next full rendering
mImage = null;
mCanvas = null;
} else {
AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
// draw the views
// create the BufferedImage into which the layout will be rendered.
boolean newImage = false;
@@ -446,6 +462,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (mElapsedFrameTimeNanos >= 0) {
long initialTime = System_Delegate.nanoTime();
if (!mFirstFrameExecuted) {
// We need to run an initial draw call to initialize the animations
render(getContext(), mViewRoot, mCanvas, 0, 0);
// The first frame will initialize the animations
Choreographer_Delegate.doFrame(initialTime);
mFirstFrameExecuted = true;
@@ -453,14 +472,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// Second frame will move the animations
Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
}
mViewRoot.draw(mCanvas);
renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth,
mMeasuredScreenHeight);
}
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
false);
// success!
return SUCCESS.createResult();
return renderResult;
} catch (Throwable e) {
// get the real cause of the exception.
Throwable t = e;
@@ -488,7 +508,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* @return the measured width/height if measuredView is non-null, null otherwise.
*/
@SuppressWarnings("deprecation") // For the use of Pair
private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
int width, int widthMode, int height, int heightMode) {
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
@@ -1061,8 +1081,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* the component supports nested scrolling attempt that first, then use the unconsumed scroll
* part to scroll the content in the component.
*/
private void handleScrolling(View view) {
BridgeContext context = getContext();
private static void handleScrolling(BridgeContext context, View view) {
int scrollPosX = context.getScrollXPos(view);
int scrollPosY = context.getScrollYPos(view);
if (scrollPosX != 0 || scrollPosY != 0) {
@@ -1080,7 +1099,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
if (scrollPosX != 0 || scrollPosY != 0) {
view.scrollBy(scrollPosX, scrollPosY);
view.scrollTo(scrollPosX, scrollPosY);
}
}
@@ -1090,7 +1109,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
handleScrolling(child);
handleScrolling(context, child);
}
}

View File

@@ -2,8 +2,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollX="10px"
android:scrollY="30px">
android:scrollX="30px"
android:scrollY="90px">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp"
@@ -29,8 +29,8 @@
android:layout_width="200dp"
android:layout_height="400dp"
android:orientation="vertical"
android:scrollX="-30px"
android:scrollY="150px">
android:scrollX="-90px"
android:scrollY="450px">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="60dp"

View File

@@ -30,6 +30,7 @@ import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.io.FolderWrapper;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
@@ -564,7 +565,7 @@ public class Main {
sFrameworkRepo.getConfiguredResources(config),
themeName, isProjectTheme);
return new SessionParams(
SessionParams sessionParams = new SessionParams(
layoutParser,
renderingMode,
null /*used for caching*/,
@@ -574,6 +575,8 @@ public class Main {
0,
targetSdk,
getLayoutLog());
sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
return sessionParams;
}
private static LayoutLog getLayoutLog() {