FileDocCategorySizeDatePackage
RenderAction.javaAPI DocAndroid 5.1 API13612Thu Mar 12 22:22:44 GMT 2015com.android.layoutlib.bridge.impl

RenderAction

public abstract class RenderAction extends com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider
Base class for rendering action. It provides life-cycle methods to init and stop the rendering. The most important methods are: {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()} after the rendering.
param
the {@link RenderParams} implementation

Fields Summary
private static com.android.layoutlib.bridge.android.BridgeContext
sCurrentContext
The current context being rendered. This is set through {@link #acquire(long)} and {@link #init(long)}, and unset in {@link #release()}.
private final T
mParams
private com.android.layoutlib.bridge.android.BridgeContext
mContext
Constructors Summary
protected RenderAction(T params)
Creates a renderAction.

This must be followed by a call to {@link RenderAction#init()}, which act as a call to {@link RenderAction#acquire(long)}

param
params the RenderParams. This must be a copy that the action can keep


                                             
       
        mParams = params;
    
Methods Summary
public com.android.ide.common.rendering.api.Resultacquire(long timeout)
Prepares the scene for action.

This call is blocking if another rendering/inflating is currently happening, and will return whether the preparation worked. The preparation can fail if another rendering took too long and the timeout was elapsed. More than one call to this from the same thread will have no effect and will return {@link Result#SUCCESS}. After scene actions have taken place, only one call to {@link #release()} must be done.

param
timeout the time to wait if another rendering is happening.
return
whether the scene was prepared
see
#release()
throws
IllegalStateException if {@link #init(long)} was never called.

        if (mContext == null) {
            throw new IllegalStateException("After scene creation, #init() must be called");
        }

        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
        // the result.
        Result result = acquireLock(timeout);
        if (result != null) {
            return result;
        }

        setUp();

        return SUCCESS.createResult();
    
private com.android.ide.common.rendering.api.ResultacquireLock(long timeout)
Acquire the lock so that the scene can be acted upon.

This returns null if the lock was just acquired, otherwise it returns {@link Result#SUCCESS} if the lock already belonged to that thread, or another instance (see {@link Result#getStatus()}) if an error occurred.

param
timeout the time to wait if another rendering is happening.
return
null if the lock was just acquire or another result depending on the state.
throws
IllegalStateException if the current context is different than the one owned by the scene.

        ReentrantLock lock = Bridge.getLock();
        if (lock.isHeldByCurrentThread() == false) {
            try {
                boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);

                if (acquired == false) {
                    return ERROR_TIMEOUT.createResult();
                }
            } catch (InterruptedException e) {
                return ERROR_LOCK_INTERRUPTED.createResult();
            }
        } else {
            // This thread holds the lock already. Checks that this wasn't for a different context.
            // If this is called by init, mContext will be null and so should sCurrentContext
            // anyway
            if (mContext != sCurrentContext) {
                throw new IllegalStateException("Acquiring different scenes from same thread without releases");
            }
            return SUCCESS.createResult();
        }

        return null;
    
protected voidcheckLock()
Checks that the lock is owned by the current thread and that the current context is the one from this scene.

throws
IllegalStateException if the current context is different than the one owned by the scene, or if {@link #acquire(long)} was not called.

        ReentrantLock lock = Bridge.getLock();
        if (lock.isHeldByCurrentThread() == false) {
            throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
        }
        if (sCurrentContext != mContext) {
            throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
        }
    
private android.content.res.ConfigurationgetConfiguration()

        Configuration config = new Configuration();

        HardwareConfig hardwareConfig = mParams.getHardwareConfig();

        ScreenSize screenSize = hardwareConfig.getScreenSize();
        if (screenSize != null) {
            switch (screenSize) {
                case SMALL:
                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL;
                    break;
                case NORMAL:
                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL;
                    break;
                case LARGE:
                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
                    break;
                case XLARGE:
                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
                    break;
            }
        }

        Density density = hardwareConfig.getDensity();
        if (density == null) {
            density = Density.MEDIUM;
        }

        config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
        config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
        if (config.screenHeightDp < config.screenWidthDp) {
            config.smallestScreenWidthDp = config.screenHeightDp;
        } else {
            config.smallestScreenWidthDp = config.screenWidthDp;
        }
        config.densityDpi = density.getDpiValue();

        // never run in compat mode:
        config.compatScreenWidthDp = config.screenWidthDp;
        config.compatScreenHeightDp = config.screenHeightDp;

        ScreenOrientation orientation = hardwareConfig.getOrientation();
        if (orientation != null) {
            switch (orientation) {
            case PORTRAIT:
                config.orientation = Configuration.ORIENTATION_PORTRAIT;
                break;
            case LANDSCAPE:
                config.orientation = Configuration.ORIENTATION_LANDSCAPE;
                break;
            case SQUARE:
                config.orientation = Configuration.ORIENTATION_SQUARE;
                break;
            }
        } else {
            config.orientation = Configuration.ORIENTATION_UNDEFINED;
        }

        // TODO: fill in more config info.

        return config;
    
protected com.android.layoutlib.bridge.android.BridgeContextgetContext()

        return mContext;
    
public static com.android.layoutlib.bridge.android.BridgeContextgetCurrentContext()

        return sCurrentContext;
    
public java.lang.IntegergetId(com.android.resources.ResourceType resType, java.lang.String resName)

        return Bridge.getResourceId(resType, resName);
    
public com.android.ide.common.rendering.api.LayoutLoggetLog()
Returns the log associated with the session.

return
the log or null if there are none.

        if (mParams != null) {
            return mParams.getLog();
        }

        return null;
    
protected TgetParams()

        return mParams;
    
public com.android.ide.common.rendering.api.Resultinit(long timeout)
Initializes and acquires the scene, creating various Android objects such as context, inflater, and parser.

param
timeout the time to wait if another rendering is happening.
return
whether the scene was prepared
see
#acquire(long)
see
#release()

        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
        // the result.
        Result result = acquireLock(timeout);
        if (result != null) {
            return result;
        }

        HardwareConfig hardwareConfig = mParams.getHardwareConfig();

        // setup the display Metrics.
        DisplayMetrics metrics = new DisplayMetrics();
        metrics.densityDpi = metrics.noncompatDensityDpi =
                hardwareConfig.getDensity().getDpiValue();

        metrics.density = metrics.noncompatDensity =
                metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;

        metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;

        metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth();
        metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight();
        metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi();
        metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi();

        RenderResources resources = mParams.getResources();

        // build the context
        mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
                mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
                mParams.isRtlSupported());

        setUp();

        return SUCCESS.createResult();
    
public voidrelease()
Cleans up the scene after an action.

        ReentrantLock lock = Bridge.getLock();

        // with the use of finally blocks, it is possible to find ourself calling this
        // without a successful call to prepareScene. This test makes sure that unlock() will
        // not throw IllegalMonitorStateException.
        if (lock.isHeldByCurrentThread()) {
            tearDown();
            lock.unlock();
        }
    
private voidsetUp()
Sets up the session for rendering.

The counterpart is {@link #tearDown()}.

        // make sure the Resources object references the context (and other objects) for this
        // scene
        mContext.initResources();
        sCurrentContext = mContext;

        // create an InputMethodManager
        InputMethodManager.getInstance();

        LayoutLog currentLog = mParams.getLog();
        Bridge.setLog(currentLog);
        mContext.getRenderResources().setFrameworkResourceIdProvider(this);
        mContext.getRenderResources().setLogger(currentLog);
    
private voidtearDown()
Tear down the session after rendering.

The counterpart is {@link #setUp()}.

        // The context may be null, if there was an error during init().
        if (mContext != null) {
            // Make sure to remove static references, otherwise we could not unload the lib
            mContext.disposeResources();
        }

        if (sCurrentContext != null) {
            // quit HandlerThread created during this session.
            HandlerThread_Delegate.cleanUp(sCurrentContext);
        }

        // clear the stored ViewConfiguration since the map is per density and not per context.
        ViewConfiguration_Accessor.clearConfigurations();

        // remove the InputMethodManager
        InputMethodManager_Accessor.resetInstance();

        sCurrentContext = null;

        Bridge.setLog(null);
        if (mContext != null) {
            mContext.getRenderResources().setFrameworkResourceIdProvider(null);
            mContext.getRenderResources().setLogger(null);
        }