Exemplo n.º 1
0
  /**
   * Searches for, and returns a {@link ResourceValue} by its name, and type.
   *
   * @param resType the type of the resource
   * @param resName the name of the resource
   * @param frameworkOnly if <code>true</code>, the method does not search in the project resources
   */
  private ResourceValue findResValue(ResourceType resType, String resName, boolean frameworkOnly) {
    // map of ResourceValue for the given type
    Map<String, ResourceValue> typeMap;

    // if allowed, search in the project resources first.
    if (!frameworkOnly) {
      typeMap = mProjectResources.get(resType);
      ResourceValue item = typeMap.get(resName);
      if (item != null) {
        return item;
      }
    }

    // now search in the framework resources.
    typeMap = mFrameworkResources.get(resType);
    ResourceValue item = typeMap.get(resName);
    if (item != null) {
      return item;
    }

    // if it was not found and the type is an id, it is possible that the ID was
    // generated dynamically when compiling the framework resources.
    // Look for it in the R map.
    if (mFrameworkProvider != null && resType == ResourceType.ID) {
      if (mFrameworkProvider.getId(resType, resName) != null) {
        return new ResourceValue(resType, resName, true);
      }
    }

    // didn't find the resource anywhere.
    if (mLogger != null) {
      mLogger.warning(
          LayoutLog.TAG_RESOURCES_RESOLVE,
          "Couldn't resolve resource @"
              + (frameworkOnly ? "android:" : "")
              + resType
              + "/"
              + resName,
          new ResourceValue(resType, resName, frameworkOnly));
    }
    return null;
  }
Exemplo n.º 2
0
  @Override
  public ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
    if (reference == null) {
      return null;
    }

    ResourceUrl resource = ResourceUrl.parse(reference);
    if (resource != null && resource.hasValidName()) {
      if (resource.theme) {
        // no theme? no need to go further!
        if (mDefaultTheme == null) {
          return null;
        }

        if (resource.type != ResourceType.ATTR) {
          // At this time, no support for ?type/name where type is not "attr"
          return null;
        }

        // Now look for the item in the theme, starting with the current one.
        ResourceValue item =
            findItemInTheme(resource.name, forceFrameworkOnly || resource.framework);
        if (item == null && mLogger != null) {
          mLogger.warning(
              LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
              String.format("Couldn't find theme resource %1$s for the current theme", reference),
              new ResourceValue(ResourceType.ATTR, reference, resource.framework));
        }

        return item;
      } else {
        return findResValue(resource.type, resource.name, forceFrameworkOnly || resource.framework);
      }
    }

    // Looks like the value didn't reference anything. Return null.
    return null;
  }
  /**
   * Instantiate a class object, using a specific constructor and parameters.
   *
   * @param clazz the class to instantiate
   * @param constructorSignature the signature of the constructor to use
   * @param constructorParameters the parameters to use in the constructor.
   * @return A new class object, created using a specific constructor and parameters.
   * @throws Exception
   */
  @SuppressWarnings("unchecked")
  private Object instantiateClass(
      Class<?> clazz, Class[] constructorSignature, Object[] constructorParameters)
      throws Exception {
    Constructor<?> constructor = null;

    try {
      constructor = clazz.getConstructor(constructorSignature);

    } catch (NoSuchMethodException e) {
      // Custom views can either implement a 3-parameter, 2-parameter or a
      // 1-parameter. Let's synthetically build and try all the alternatives.
      // That's kind of like switching to the other box.
      //
      // The 3-parameter constructor takes the following arguments:
      // ...(Context context, AttributeSet attrs, int defStyle)

      int n = constructorSignature.length;
      if (n == 0) {
        // There is no parameter-less constructor. Nobody should ask for one.
        throw e;
      }

      for (int i = 3; i >= 1; i--) {
        if (i == n) {
          // Let's skip the one we know already fails
          continue;
        }
        Class[] sig = new Class[i];
        Object[] params = new Object[i];

        int k = i;
        if (n < k) {
          k = n;
        }
        System.arraycopy(constructorSignature, 0, sig, 0, k);
        System.arraycopy(constructorParameters, 0, params, 0, k);

        for (k++; k <= i; k++) {
          if (k == 2) {
            // Parameter 2 is the AttributeSet
            sig[k - 1] = clazz.getClassLoader().loadClass("android.util.AttributeSet");
            params[k - 1] = null;

          } else if (k == 3) {
            // Parameter 3 is the int defstyle
            sig[k - 1] = int.class;
            params[k - 1] = 0;
          }
        }

        constructorSignature = sig;
        constructorParameters = params;

        try {
          // Try again...
          constructor = clazz.getConstructor(constructorSignature);
          if (constructor != null) {
            // Found a suitable constructor, now let's use it.
            // (But let's warn the user if the simple View constructor was found
            // since Unexpected Things may happen if the attribute set constructors
            // are not found)
            if (constructorSignature.length < 2 && mLogger != null) {
              mLogger.warning(
                  "wrongconstructor", //$NON-NLS-1$
                  String.format(
                      "Custom view %1$s is not using the 2- or 3-argument "
                          + "View constructors; XML attributes will not work",
                      clazz.getSimpleName()),
                  null /*data*/);
            }
            break;
          }
        } catch (NoSuchMethodException e1) {
          // pass
        }
      }

      // If all the alternatives failed, throw the initial exception.
      if (constructor == null) {
        throw e;
      }
    }

    constructor.setAccessible(true);
    return constructor.newInstance(constructorParameters);
  }