am cd6e00c6: Merge changes from topic \'layoutlib-api-15\' into lmp-mr1-dev

* commit 'cd6e00c6d973af350f4bb0de5d85fed7e299d9e8':
  Update golden image for tests.
  Update to using LayoutlibCallback.
  Remove implementation of deprecated method.
  Add @empty support.
This commit is contained in:
Deepanshu Gupta
2015-04-16 17:19:42 +00:00
committed by Android Git Automerger
18 changed files with 224 additions and 164 deletions

View File

@ -16,7 +16,7 @@
package android.app;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.Context;
@ -30,19 +30,19 @@ import android.os.Bundle;
*
* The methods being re-implemented are the ones responsible for instantiating Fragment objects.
* Because the classes of these objects are found in the project, these methods need access to
* {@link IProjectCallback} object. They are however static methods, so the callback is set
* before the inflation through {@link #setProjectCallback(IProjectCallback)}.
* {@link LayoutlibCallback} object. They are however static methods, so the callback is set
* before the inflation through {@link #setLayoutlibCallback(LayoutlibCallback)}.
*/
public class Fragment_Delegate {
private static IProjectCallback sProjectCallback;
private static LayoutlibCallback sLayoutlibCallback;
/**
* Sets the current {@link IProjectCallback} to be used to instantiate classes coming
* Sets the current {@link LayoutlibCallback} to be used to instantiate classes coming
* from the project being rendered.
*/
public static void setProjectCallback(IProjectCallback projectCallback) {
sProjectCallback = projectCallback;
public static void setLayoutlibCallback(LayoutlibCallback layoutlibCallback) {
sLayoutlibCallback = layoutlibCallback;
}
/**
@ -62,17 +62,17 @@ public class Fragment_Delegate {
* This is currently just used to get its ClassLoader.
* @param fname The class name of the fragment to instantiate.
* @param args Bundle of arguments to supply to the fragment, which it
* can retrieve with {@link #getArguments()}. May be null.
* can retrieve with {@link Fragment#getArguments()}. May be null.
* @return Returns a new fragment instance.
* @throws InstantiationException If there is a failure in instantiating
* @throws Fragment.InstantiationException If there is a failure in instantiating
* the given fragment class. This is a runtime exception; it is not
* normally expected to happen.
*/
@LayoutlibDelegate
/*package*/ static Fragment instantiate(Context context, String fname, Bundle args) {
try {
if (sProjectCallback != null) {
Fragment f = (Fragment) sProjectCallback.loadView(fname,
if (sLayoutlibCallback != null) {
Fragment f = (Fragment) sLayoutlibCallback.loadView(fname,
new Class[0], new Object[0]);
if (args != null) {

View File

@ -16,8 +16,8 @@
package android.content.res;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
@ -49,7 +49,7 @@ import java.io.InputStream;
public final class BridgeResources extends Resources {
private BridgeContext mContext;
private IProjectCallback mProjectCallback;
private LayoutlibCallback mLayoutlibCallback;
private boolean[] mPlatformResourceFlag = new boolean[1];
private TypedValue mTmpValue = new TypedValue();
@ -94,12 +94,12 @@ public final class BridgeResources extends Resources {
AssetManager assets,
DisplayMetrics metrics,
Configuration config,
IProjectCallback projectCallback) {
LayoutlibCallback layoutlibCallback) {
return Resources.mSystem = new BridgeResources(context,
assets,
metrics,
config,
projectCallback);
layoutlibCallback);
}
/**
@ -109,16 +109,16 @@ public final class BridgeResources extends Resources {
public static void disposeSystem() {
if (Resources.mSystem instanceof BridgeResources) {
((BridgeResources)(Resources.mSystem)).mContext = null;
((BridgeResources)(Resources.mSystem)).mProjectCallback = null;
((BridgeResources)(Resources.mSystem)).mLayoutlibCallback = null;
}
Resources.mSystem = null;
}
private BridgeResources(BridgeContext context, AssetManager assets, DisplayMetrics metrics,
Configuration config, IProjectCallback projectCallback) {
Configuration config, LayoutlibCallback layoutlibCallback) {
super(assets, metrics, config);
mContext = context;
mProjectCallback = projectCallback;
mLayoutlibCallback = layoutlibCallback;
}
public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) {
@ -138,8 +138,8 @@ public final class BridgeResources extends Resources {
}
// didn't find a match in the framework? look in the project.
if (mProjectCallback != null) {
resourceInfo = mProjectCallback.resolveResourceId(id);
if (mLayoutlibCallback != null) {
resourceInfo = mLayoutlibCallback.resolveResourceId(id);
if (resourceInfo != null) {
platformResFlag_out[0] = false;
@ -153,11 +153,6 @@ public final class BridgeResources extends Resources {
return null;
}
@Override
public Drawable getDrawable(int id) throws NotFoundException {
return getDrawable(id, null);
}
@Override
public Drawable getDrawable(int id, Theme theme) {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
@ -257,7 +252,7 @@ public final class BridgeResources extends Resources {
try {
// check if the current parser can provide us with a custom parser.
if (mPlatformResourceFlag[0] == false) {
parser = mProjectCallback.getParser(value);
parser = mLayoutlibCallback.getParser(value);
}
// create a new one manually if needed.
@ -692,8 +687,8 @@ public final class BridgeResources extends Resources {
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
// if the name is unknown in the framework, get it from the custom view loader.
if (resourceInfo == null && mProjectCallback != null) {
resourceInfo = mProjectCallback.resolveResourceId(id);
if (resourceInfo == null && mLayoutlibCallback != null) {
resourceInfo = mLayoutlibCallback.resolveResourceId(id);
}
String message = null;

View File

@ -16,6 +16,7 @@
package android.content.res;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.AttrResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources;
@ -40,9 +41,12 @@ import android.view.LayoutInflater_Delegate;
import android.view.ViewGroup.LayoutParams;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import static com.android.ide.common.rendering.api.RenderResources.*;
/**
* Custom implementation of TypedArray to handle non compiled resources.
*/
@ -56,6 +60,11 @@ public final class BridgeTypedArray extends TypedArray {
private final String[] mNames;
private final boolean[] mIsFramework;
// Contains ids that are @empty. We still store null in mResourceData for that index, since we
// want to save on the check against empty, each time a resource value is requested.
@Nullable
private int[] mEmptyIds;
public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
boolean platformFile) {
super(resources, null, null, 0);
@ -90,19 +99,32 @@ public final class BridgeTypedArray extends TypedArray {
// fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
// first count the array size
int count = 0;
ArrayList<Integer> emptyIds = null;
for (int i = 0; i < mResourceData.length; i++) {
ResourceValue data = mResourceData[i];
if (data != null) {
if (RenderResources.REFERENCE_NULL.equals(data.getValue())) {
// No need to store this resource value. This saves needless checking for
// "@null" every time an attribute is requested.
String dataValue = data.getValue();
if (REFERENCE_NULL.equals(dataValue) || REFERENCE_UNDEFINED.equals(dataValue)) {
mResourceData[i] = null;
} else if (REFERENCE_EMPTY.equals(dataValue)) {
mResourceData[i] = null;
if (emptyIds == null) {
emptyIds = new ArrayList<Integer>(4);
}
emptyIds.add(i);
} else {
count++;
}
}
}
if (emptyIds != null) {
mEmptyIds = new int[emptyIds.size()];
for (int i = 0; i < emptyIds.size(); i++) {
mEmptyIds[i] = emptyIds.get(i);
}
}
// allocate the table with an extra to store the size
mIndices = new int[count+1];
mIndices[0] = count;
@ -624,7 +646,7 @@ public final class BridgeTypedArray extends TypedArray {
if (isFrameworkId) {
idValue = Bridge.getResourceId(ResourceType.ID, idName);
} else {
idValue = mContext.getProjectCallback().getResourceId(ResourceType.ID, idName);
idValue = mContext.getLayoutlibCallback().getResourceId(ResourceType.ID, idName);
}
return idValue == null ? defValue : idValue;
}
@ -644,7 +666,7 @@ public final class BridgeTypedArray extends TypedArray {
idValue = Bridge.getResourceId(resValue.getResourceType(),
resValue.getName());
} else {
idValue = mContext.getProjectCallback().getResourceId(
idValue = mContext.getLayoutlibCallback().getResourceId(
resValue.getResourceType(), resValue.getName());
}
@ -748,6 +770,12 @@ public final class BridgeTypedArray extends TypedArray {
return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
}
@Override
public boolean hasValueOrEmpty(int index) {
return hasValue(index) || index >= 0 && index < mResourceData.length &&
mEmptyIds != null && Arrays.binarySearch(mEmptyIds, index) >= 0;
}
/**
* Retrieve the raw TypedValue for the attribute at <var>index</var>
* and return a temporary object holding its data. This object is only

View File

@ -69,8 +69,8 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes {
// this is not an attribute in the android namespace, we query the customviewloader, if
// the namespaces match.
if (mContext.getProjectCallback().getNamespace().equals(ns)) {
Integer v = mContext.getProjectCallback().getResourceId(ResourceType.ATTR, name);
if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) {
Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name);
if (v != null) {
return v.intValue();
}
@ -273,7 +273,7 @@ public class BridgeXmlPullAttributes extends XmlPullAttributes {
if (mPlatformFile || resource.isFramework()) {
id = Bridge.getResourceId(resource.getResourceType(), resource.getName());
} else {
id = mContext.getProjectCallback().getResourceId(
id = mContext.getLayoutlibCallback().getResourceId(
resource.getResourceType(), resource.getName());
}

View File

@ -16,7 +16,7 @@
package android.view;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.MergeCookie;
import com.android.ide.common.rendering.api.ResourceReference;
@ -46,7 +46,7 @@ import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext;
*/
public final class BridgeInflater extends LayoutInflater {
private final IProjectCallback mProjectCallback;
private final LayoutlibCallback mLayoutlibCallback;
private boolean mIsInMerge = false;
private ResourceReference mResourceReference;
@ -64,21 +64,21 @@ public final class BridgeInflater extends LayoutInflater {
super(original, newContext);
newContext = getBaseContext(newContext);
if (newContext instanceof BridgeContext) {
mProjectCallback = ((BridgeContext) newContext).getProjectCallback();
mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback();
} else {
mProjectCallback = null;
mLayoutlibCallback = null;
}
}
/**
* Instantiate a new BridgeInflater with an {@link IProjectCallback} object.
* Instantiate a new BridgeInflater with an {@link LayoutlibCallback} object.
*
* @param context The Android application context.
* @param projectCallback the {@link IProjectCallback} object.
* @param layoutlibCallback the {@link LayoutlibCallback} object.
*/
public BridgeInflater(Context context, IProjectCallback projectCallback) {
public BridgeInflater(Context context, LayoutlibCallback layoutlibCallback) {
super(context);
mProjectCallback = projectCallback;
mLayoutlibCallback = layoutlibCallback;
mConstructorArgs[0] = context;
}
@ -167,12 +167,13 @@ public final class BridgeInflater extends LayoutInflater {
ResourceValue value = null;
@SuppressWarnings("deprecation")
Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource);
if (layoutInfo != null) {
value = bridgeContext.getRenderResources().getFrameworkResource(
ResourceType.LAYOUT, layoutInfo.getSecond());
} else {
layoutInfo = mProjectCallback.resolveResourceId(resource);
layoutInfo = mLayoutlibCallback.resolveResourceId(resource);
if (layoutInfo != null) {
value = bridgeContext.getRenderResources().getProjectResource(
@ -203,7 +204,7 @@ public final class BridgeInflater extends LayoutInflater {
}
private View loadCustomView(String name, AttributeSet attrs) throws Exception {
if (mProjectCallback != null) {
if (mLayoutlibCallback != null) {
// first get the classname in case it's not the node name
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
@ -211,7 +212,7 @@ public final class BridgeInflater extends LayoutInflater {
mConstructorArgs[1] = attrs;
Object customView = mProjectCallback.loadView(name, mConstructorSignature,
Object customView = mLayoutlibCallback.loadView(name, mConstructorSignature,
mConstructorArgs);
if (customView instanceof View) {

View File

@ -43,7 +43,7 @@ public class PolicyManager {
}
public static LayoutInflater makeNewLayoutInflater(Context context) {
return new BridgeInflater(context, RenderAction.getCurrentContext().getProjectCallback());
return new BridgeInflater(context, RenderAction.getCurrentContext().getLayoutlibCallback());
}
public static WindowManagerPolicy makeNewWindowManager() {

View File

@ -20,8 +20,8 @@ import android.os.IBinder;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.ide.common.rendering.api.ResourceValue;
@ -113,7 +113,7 @@ public final class BridgeContext extends Context {
private final RenderResources mRenderResources;
private final Configuration mConfig;
private final ApplicationInfo mApplicationInfo;
private final IProjectCallback mProjectCallback;
private final LayoutlibCallback mLayoutlibCallback;
private final WindowManager mWindowManager;
private final DisplayManager mDisplayManager;
@ -147,13 +147,13 @@ public final class BridgeContext extends Context {
public BridgeContext(Object projectKey, DisplayMetrics metrics,
RenderResources renderResources,
AssetRepository assets,
IProjectCallback projectCallback,
LayoutlibCallback layoutlibCallback,
Configuration config,
int targetSdkVersion,
boolean hasRtlSupport) {
mProjectKey = projectKey;
mMetrics = metrics;
mProjectCallback = projectCallback;
mLayoutlibCallback = layoutlibCallback;
mRenderResources = renderResources;
mConfig = config;
@ -172,7 +172,7 @@ public final class BridgeContext extends Context {
/**
* Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
* {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}.
* {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}.
*
* @see #disposeResources()
*/
@ -184,7 +184,7 @@ public final class BridgeContext extends Context {
assetManager,
mMetrics,
mConfig,
mProjectCallback);
mLayoutlibCallback);
mTheme = mSystemResources.newTheme();
}
@ -223,8 +223,8 @@ public final class BridgeContext extends Context {
return mMetrics;
}
public IProjectCallback getProjectCallback() {
return mProjectCallback;
public LayoutlibCallback getLayoutlibCallback() {
return mLayoutlibCallback;
}
public RenderResources getRenderResources() {
@ -283,7 +283,7 @@ public final class BridgeContext extends Context {
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
boolean isFrameworkRes = true;
if (resourceInfo == null) {
resourceInfo = mProjectCallback.resolveResourceId(resid);
resourceInfo = mLayoutlibCallback.resolveResourceId(resid);
isFrameworkRes = false;
}
@ -339,8 +339,8 @@ public final class BridgeContext extends Context {
}
// didn't find a match in the framework? look in the project.
if (mProjectCallback != null) {
resourceInfo = mProjectCallback.resolveResourceId(id);
if (mLayoutlibCallback != null) {
resourceInfo = mLayoutlibCallback.resolveResourceId(id);
if (resourceInfo != null) {
return new ResourceReference(resourceInfo.getSecond(), false);
@ -438,9 +438,9 @@ public final class BridgeContext extends Context {
private ILayoutPullParser getParser(ResourceReference resource) {
ILayoutPullParser parser;
if (resource instanceof ResourceValue) {
parser = mProjectCallback.getParser((ResourceValue) resource);
parser = mLayoutlibCallback.getParser((ResourceValue) resource);
} else {
parser = mProjectCallback.getParser(resource.getName());
parser = mLayoutlibCallback.getParser(resource.getName());
}
return parser;
}
@ -665,7 +665,7 @@ public final class BridgeContext extends Context {
boolean isFrameworkRes = true;
Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
if (value == null) {
value = mProjectCallback.resolveResourceId(defStyleRes);
value = mLayoutlibCallback.resolveResourceId(defStyleRes);
isFrameworkRes = false;
}
@ -703,7 +703,7 @@ public final class BridgeContext extends Context {
}
}
String appNamespace = mProjectCallback.getNamespace();
String appNamespace = mLayoutlibCallback.getNamespace();
if (attributeList != null) {
for (int index = 0 ; index < attributeList.size() ; index++) {
@ -846,7 +846,7 @@ public final class BridgeContext extends Context {
if (resolvedResource != null) {
isFramework = true;
} else {
resolvedResource = mProjectCallback.resolveResourceId(attr);
resolvedResource = mLayoutlibCallback.resolveResourceId(attr);
}
if (resolvedResource != null) {
@ -872,7 +872,7 @@ public final class BridgeContext extends Context {
return Pair.of(info.getSecond(), Boolean.TRUE);
}
info = mProjectCallback.resolveResourceId(attr);
info = mLayoutlibCallback.resolveResourceId(attr);
if (info != null) {
return Pair.of(info.getSecond(), Boolean.FALSE);
}
@ -924,8 +924,8 @@ public final class BridgeContext extends Context {
// getResourceId creates a new resource id if an existing resource id isn't found. So, we
// check for the existence of the resource before calling it.
if (getRenderResources().getProjectResource(resType, resName) != null) {
if (mProjectCallback != null) {
Integer value = mProjectCallback.getResourceId(resType, resName);
if (mLayoutlibCallback != null) {
Integer value = mLayoutlibCallback.getResourceId(resType, resName);
if (value != null) {
return value;
}

View File

@ -18,8 +18,8 @@ package com.android.layoutlib.bridge.android.support;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
@ -30,7 +30,6 @@ import android.view.View;
import android.widget.LinearLayout;
import java.lang.reflect.Method;
import java.util.HashMap;
import static com.android.layoutlib.bridge.util.ReflectionUtils.*;
@ -61,7 +60,7 @@ public class RecyclerViewUtil {
public static void setAdapter(@NonNull View recyclerView, @NonNull BridgeContext context,
@NonNull SessionParams params) {
try {
setLayoutManager(recyclerView, context, params.getProjectCallback());
setLayoutManager(recyclerView, context, params.getLayoutlibCallback());
Object adapter = createAdapter(params);
setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter");
} catch (ReflectionException e) {
@ -71,7 +70,7 @@ public class RecyclerViewUtil {
}
private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context,
@NonNull IProjectCallback callback) throws ReflectionException {
@NonNull LayoutlibCallback callback) throws ReflectionException {
Object cookie = context.getCookie(recyclerView);
assert cookie == null || cookie instanceof LayoutManagerType || cookie instanceof String;
if (!(cookie instanceof LayoutManagerType)) {
@ -90,7 +89,7 @@ public class RecyclerViewUtil {
@Nullable
private static Object createLayoutManager(@Nullable LayoutManagerType type,
@NonNull Context context, @NonNull IProjectCallback callback)
@NonNull Context context, @NonNull LayoutlibCallback callback)
throws ReflectionException {
if (type == null) {
type = LayoutManagerType.getDefault();
@ -109,7 +108,7 @@ public class RecyclerViewUtil {
return null;
}
try {
return params.getProjectCallback().loadView(CN_ADAPTER, new Class[0], new Object[0]);
return params.getLayoutlibCallback().loadView(CN_ADAPTER, new Class[0], new Object[0]);
} catch (Exception e) {
throw new ReflectionException(e);
}

View File

@ -70,7 +70,7 @@ public class AppCompatActionBar extends BridgeActionBar {
try {
Class[] constructorParams = {View.class};
Object[] constructorArgs = {getDecorContent()};
mWindowDecorActionBar = params.getProjectCallback().loadView(WINDOW_ACTION_BAR_CLASS,
mWindowDecorActionBar = params.getLayoutlibCallback().loadView(WINDOW_ACTION_BAR_CLASS,
constructorParams, constructorArgs);
mWindowActionBarClass = mWindowDecorActionBar == null ? null :

View File

@ -51,7 +51,7 @@ public abstract class BridgeActionBar {
@NonNull ViewGroup parentView) {
mBridgeContext = context;
mParams = params;
mCallback = params.getProjectCallback().getActionBarCallback();
mCallback = params.getLayoutlibCallback().getActionBarCallback();
ResourceValue layoutName = getLayoutResource(context);
if (layoutName == null) {
throw new RuntimeException("Unable to find the layout for Action Bar.");

View File

@ -16,10 +16,6 @@
package com.android.layoutlib.bridge.impl;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderParams;
@ -43,6 +39,10 @@ import android.view.inputmethod.InputMethodManager_Accessor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
/**
* Base class for rendering action.
*
@ -120,7 +120,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
// build the context
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
mParams.getAssets(), mParams.getProjectCallback(), getConfiguration(),
mParams.getAssets(), mParams.getLayoutlibCallback(), getConfiguration(),
mParams.getTargetSdkVersion(), mParams.isRtlSupported());
setUp();

View File

@ -16,20 +16,13 @@
package com.android.layoutlib.bridge.impl;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceReference;
@ -54,13 +47,13 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.android.SessionParamsFlags;
import com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
import com.android.layoutlib.bridge.bars.BridgeActionBar;
import com.android.layoutlib.bridge.bars.AppCompatActionBar;
import com.android.layoutlib.bridge.bars.BridgeActionBar;
import com.android.layoutlib.bridge.bars.Config;
import com.android.layoutlib.bridge.bars.FrameworkActionBar;
import com.android.layoutlib.bridge.bars.NavigationBar;
import com.android.layoutlib.bridge.bars.StatusBar;
import com.android.layoutlib.bridge.bars.TitleBar;
import com.android.layoutlib.bridge.bars.FrameworkActionBar;
import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
import com.android.resources.Density;
@ -116,6 +109,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
/**
* Class implementing the render session.
* <p/>
@ -219,7 +219,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
// build the inflater and parser.
mInflater = new BridgeInflater(context, params.getProjectCallback());
mInflater = new BridgeInflater(context, params.getLayoutlibCallback());
context.setBridgeInflater(mInflater);
mBlockParser = new BridgeXmlBlockParser(
@ -401,7 +401,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// Sets the project callback (custom view loader) to the fragment delegate so that
// it can instantiate the custom Fragment.
Fragment_Delegate.setProjectCallback(params.getProjectCallback());
Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback());
String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG);
boolean isPreference = "PreferenceScreen".equals(rootTag);
@ -416,13 +416,13 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// done with the parser, pop it.
context.popParser();
Fragment_Delegate.setProjectCallback(null);
Fragment_Delegate.setLayoutlibCallback(null);
// set the AttachInfo on the root view.
AttachInfo_Accessor.setAttachInfo(mViewRoot);
// post-inflate process. For now this supports TabHost/TabWidget
postInflateProcess(view, params.getProjectCallback(), isPreference ? view : null);
postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null);
// get the background drawable
if (mWindowBackground != null) {
@ -675,7 +675,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
animationResource = context.getRenderResources().getProjectResource(
ResourceType.ANIMATOR, animationName);
if (animationResource != null) {
animationId = context.getProjectCallback().getResourceId(
animationId = context.getLayoutlibCallback().getResourceId(
ResourceType.ANIMATOR, animationName);
}
}
@ -1246,17 +1246,17 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
* based on the content of the {@link FrameLayout}.
* @param view the root view to process.
* @param projectCallback callback to the project.
* @param layoutlibCallback callback to the project.
* @param skip the view and it's children are not processed.
*/
@SuppressWarnings("deprecation") // For the use of Pair
private void postInflateProcess(View view, IProjectCallback projectCallback, View skip)
private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip)
throws PostInflateException {
if (view == skip) {
return;
}
if (view instanceof TabHost) {
setupTabHost((TabHost) view, projectCallback);
setupTabHost((TabHost) view, layoutlibCallback);
} else if (view instanceof QuickContactBadge) {
QuickContactBadge badge = (QuickContactBadge) view;
badge.setImageToDefault();
@ -1275,8 +1275,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// if there was no adapter binding, trying to get it from the call back.
if (binding == null) {
binding = params.getProjectCallback().getAdapterBinding(listRef,
context.getViewKey(view), view);
binding = layoutlibCallback.getAdapterBinding(
listRef, context.getViewKey(view), view);
}
if (binding != null) {
@ -1292,7 +1292,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
for (int i = 0; i < count; i++) {
Pair<View, Boolean> pair = context.inflateView(
binding.getHeaderAt(i),
list, false /*attachToRoot*/, skipCallbackParser);
list, false, skipCallbackParser);
if (pair.getFirst() != null) {
list.addHeaderView(pair.getFirst());
}
@ -1304,7 +1304,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
for (int i = 0; i < count; i++) {
Pair<View, Boolean> pair = context.inflateView(
binding.getFooterAt(i),
list, false /*attachToRoot*/, skipCallbackParser);
list, false, skipCallbackParser);
if (pair.getFirst() != null) {
list.addFooterView(pair.getFirst());
}
@ -1315,17 +1315,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (view instanceof ExpandableListView) {
((ExpandableListView) view).setAdapter(
new FakeExpandableAdapter(
listRef, binding, params.getProjectCallback()));
new FakeExpandableAdapter(listRef, binding, layoutlibCallback));
} else {
((AbsListView) view).setAdapter(
new FakeAdapter(
listRef, binding, params.getProjectCallback()));
new FakeAdapter(listRef, binding, layoutlibCallback));
}
} else if (view instanceof AbsSpinner) {
((AbsSpinner) view).setAdapter(
new FakeAdapter(
listRef, binding, params.getProjectCallback()));
new FakeAdapter(listRef, binding, layoutlibCallback));
}
}
}
@ -1336,7 +1333,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
final int count = group.getChildCount();
for (int c = 0; c < count; c++) {
View child = group.getChildAt(c);
postInflateProcess(child, projectCallback, skip);
postInflateProcess(child, layoutlibCallback, skip);
}
}
}
@ -1360,10 +1357,10 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
/**
* Sets up a {@link TabHost} object.
* @param tabHost the TabHost to setup.
* @param projectCallback The project callback object to access the project R class.
* @param layoutlibCallback The project callback object to access the project R class.
* @throws PostInflateException
*/
private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback)
throws PostInflateException {
// look for the TabWidget, and the FrameLayout. They have their own specific names
View v = tabHost.findViewById(android.R.id.tabs);
@ -1406,8 +1403,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (count == 0) {
// Create a dummy child to get a single tab
TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label",
tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details))
TabSpec spec = tabHost.newTabSpec("tag")
.setIndicator("Tab Label", tabHost.getResources()
.getDrawable(android.R.drawable.ic_menu_info_details, null))
.setContent(new TabHost.TabContentFactory() {
@Override
public View createTabContent(String tag) {
@ -1423,7 +1421,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
@SuppressWarnings("ConstantConditions") // child cannot be null.
int id = child.getId();
@SuppressWarnings("deprecation")
Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id);
String name;
if (resource != null) {
name = resource.getSecond();

View File

@ -17,7 +17,7 @@
package com.android.layoutlib.bridge.impl.binding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute;
@ -40,7 +40,7 @@ import android.widget.TextView;
public class AdapterHelper {
static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
// we don't care about recycling here because we never scroll.
DataBindingItem dataBindingItem = item.getDataBindingItem();
@ -65,7 +65,7 @@ public class AdapterHelper {
}
private static void fillView(BridgeContext context, View view, AdapterItem item,
AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) {
AdapterItem parentItem, LayoutlibCallback callback, ResourceReference adapterRef) {
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
final int count = group.getChildCount();

View File

@ -18,7 +18,7 @@ package com.android.layoutlib.bridge.impl.binding;
import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.util.Pair;
@ -37,18 +37,17 @@ import java.util.List;
* and {@link SpinnerAdapter}.
*
*/
@SuppressWarnings("deprecation")
public class FakeAdapter extends BaseAdapter {
// don't use a set because the order is important.
private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>();
private final IProjectCallback mCallback;
private final LayoutlibCallback mCallback;
private final ResourceReference mAdapterRef;
private final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
private boolean mSkipCallbackParser = false;
public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
LayoutlibCallback callback) {
mAdapterRef = adapterRef;
mCallback = callback;
@ -111,11 +110,11 @@ public class FakeAdapter extends BaseAdapter {
public View getView(int position, View convertView, ViewGroup parent) {
// we don't care about recycling here because we never scroll.
AdapterItem item = mItems.get(position);
Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentGroup*/, parent,
mCallback, mAdapterRef, mSkipCallbackParser);
@SuppressWarnings("deprecation")
Pair<View, Boolean> pair = AdapterHelper.getView(item, null, parent, mCallback,
mAdapterRef, mSkipCallbackParser);
mSkipCallbackParser = pair.getSecond();
return pair.getFirst();
}
@Override

View File

@ -18,7 +18,7 @@ package com.android.layoutlib.bridge.impl.binding;
import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.util.Pair;
@ -34,7 +34,7 @@ import java.util.List;
@SuppressWarnings("deprecation")
public class FakeExpandableAdapter implements ExpandableListAdapter, HeterogeneousExpandableList {
private final IProjectCallback mCallback;
private final LayoutlibCallback mCallback;
private final ResourceReference mAdapterRef;
private boolean mSkipCallbackParser = false;
@ -45,7 +45,7 @@ public class FakeExpandableAdapter implements ExpandableListAdapter, Heterogeneo
private final List<ResourceReference> mChildrenTypes = new ArrayList<ResourceReference>();
public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
LayoutlibCallback callback) {
mAdapterRef = adapterRef;
mCallback = callback;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -20,7 +20,7 @@ import com.android.SdkConstants;
import com.android.ide.common.rendering.api.ActionBarCallback;
import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.resources.ResourceType;
@ -28,10 +28,7 @@ import com.android.ide.common.resources.IntArrayWrapper;
import com.android.util.Pair;
import com.android.utils.ILogger;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -40,7 +37,7 @@ import java.util.Map;
import com.google.android.collect.Maps;
@SuppressWarnings("deprecation") // For Pair
public class LayoutLibTestCallback extends ClassLoader implements IProjectCallback {
public class LayoutLibTestCallback extends LayoutlibCallback {
private static final String PROJECT_CLASSES_LOCATION = "/testApp/MyApplication/build/intermediates/classes/debug/";
private static final String PACKAGE_NAME = "com.android.layoutlib.test.myapplication";
@ -48,16 +45,16 @@ public class LayoutLibTestCallback extends ClassLoader implements IProjectCallba
private final Map<Integer, Pair<ResourceType, String>> mProjectResources = Maps.newHashMap();
private final Map<IntArrayWrapper, String> mStyleableValueToNameMap = Maps.newHashMap();
private final Map<ResourceType, Map<String, Integer>> mResources = Maps.newHashMap();
private final Map<String, Class<?>> mClasses = Maps.newHashMap();
private final ILogger mLog;
private final ActionBarCallback mActionBarCallback = new ActionBarCallback();
private final ClassLoader mModuleClassLoader = new ModuleClassLoader(PROJECT_CLASSES_LOCATION);
public LayoutLibTestCallback(ILogger logger) {
mLog = logger;
}
public void initResources() throws ClassNotFoundException {
Class<?> rClass = loadClass(PACKAGE_NAME + ".R");
Class<?> rClass = mModuleClassLoader.loadClass(PACKAGE_NAME + ".R");
Class<?>[] nestedClasses = rClass.getDeclaredClasses();
for (Class<?> resClass : nestedClasses) {
final ResourceType resType = ResourceType.getEnum(resClass.getSimpleName());
@ -91,40 +88,11 @@ public class LayoutLibTestCallback extends ClassLoader implements IProjectCallba
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> aClass = mClasses.get(name);
if (aClass != null) {
return aClass;
}
String pathName = PROJECT_CLASSES_LOCATION.concat(name.replace('.', '/')).concat(".class");
InputStream classInputStream = getClass().getResourceAsStream(pathName);
if (classInputStream == null) {
throw new ClassNotFoundException("Unable to find class " + name + " at " + pathName);
}
byte[] data;
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
data = new byte[16384];
while ((nRead = classInputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
data = buffer.toByteArray();
} catch (IOException e) {
// Wrap the exception with ClassNotFoundException so that caller can deal with it.
throw new ClassNotFoundException("Unable to load class " + name, e);
}
aClass = defineClass(name, data, 0, data.length);
mClasses.put(name, aClass);
return aClass;
}
@Override
public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs)
throws Exception {
Class<?> viewClass = findClass(name);
Class<?> viewClass = mModuleClassLoader.loadClass(name);
Constructor<?> viewConstructor = viewClass.getConstructor(constructorSignature);
viewConstructor.setAccessible(true);
return viewConstructor.newInstance(constructorArgs);
@ -180,4 +148,9 @@ public class LayoutLibTestCallback extends ClassLoader implements IProjectCallba
public ActionBarCallback getActionBarCallback() {
return mActionBarCallback;
}
@Override
public boolean supports(int ideFeature) {
return false;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.layoutlib.bridge.intensive.setup;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import com.google.android.collect.Maps;
/**
* The ClassLoader to load the project's classes.
*/
public class ModuleClassLoader extends ClassLoader {
private final Map<String, Class<?>> mClasses = Maps.newHashMap();
private final String mClassLocation;
public ModuleClassLoader(String classLocation) {
mClassLocation = classLocation;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> aClass = mClasses.get(name);
if (aClass != null) {
return aClass;
}
String pathName = mClassLocation.concat(name.replace('.', '/')).concat(".class");
InputStream classInputStream = getClass().getResourceAsStream(pathName);
if (classInputStream == null) {
throw new ClassNotFoundException("Unable to find class " + name + " at " + pathName);
}
byte[] data;
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
data = new byte[16384]; // 16k
while ((nRead = classInputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
data = buffer.toByteArray();
} catch (IOException e) {
// Wrap the exception with ClassNotFoundException so that caller can deal with it.
throw new ClassNotFoundException("Unable to load class " + name, e);
}
aClass = defineClass(name, data, 0, data.length);
mClasses.put(name, aClass);
return aClass;
}
}