summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/view/LayoutInflater.java93
2 files changed, 77 insertions, 18 deletions
diff --git a/api/current.txt b/api/current.txt
index abab90182b01..66a4bd096aea 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -49550,6 +49550,7 @@ package android.view {
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
method public abstract android.view.LayoutInflater cloneInContext(android.content.Context);
method public final android.view.View createView(String, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
+ method @Nullable public final android.view.View createView(@NonNull android.content.Context, @NonNull String, @Nullable String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
method public static android.view.LayoutInflater from(android.content.Context);
method public android.content.Context getContext();
method public final android.view.LayoutInflater.Factory getFactory();
@@ -49561,6 +49562,7 @@ package android.view {
method public android.view.View inflate(org.xmlpull.v1.XmlPullParser, @Nullable android.view.ViewGroup, boolean);
method protected android.view.View onCreateView(String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
method protected android.view.View onCreateView(android.view.View, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
+ method @Nullable public android.view.View onCreateView(@NonNull android.content.Context, @Nullable android.view.View, @NonNull String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException;
method public void setFactory(android.view.LayoutInflater.Factory);
method public void setFactory2(android.view.LayoutInflater.Factory2);
method public void setFilter(android.view.LayoutInflater.Filter);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 6a290b7fe045..3f18d8b46e2a 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -42,14 +42,16 @@ import android.widget.FrameLayout;
import com.android.internal.R;
import dalvik.system.PathClassLoader;
-import java.io.File;
-import java.lang.reflect.Method;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
import java.util.HashMap;
+import java.util.Objects;
/**
* Instantiates a layout XML file into its corresponding {@link android.view.View}
@@ -110,7 +112,12 @@ public abstract class LayoutInflater {
// The classloader includes the generated compiled_view.dex file.
private ClassLoader mPrecompiledClassLoader;
- @UnsupportedAppUsage
+ /**
+ * This is not a public API. Two APIs are now available to alleviate the need to access
+ * this directly: {@link #createView(Context, String, String, AttributeSet)} and
+ * {@link #onCreateView(Context, View, String, AttributeSet)}.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
final Object[] mConstructorArgs = new Object[2];
@UnsupportedAppUsage
@@ -721,6 +728,32 @@ public abstract class LayoutInflater {
} while (cl != null);
return false;
}
+ /**
+ * Low-level function for instantiating a view by name. This attempts to
+ * instantiate a view class of the given <var>name</var> found in this
+ * LayoutInflater's ClassLoader. To use an explicit Context in the View
+ * constructor, use {@link #createView(Context, String, String, AttributeSet)} instead.
+ *
+ * <p>
+ * There are two things that can happen in an error case: either the
+ * exception describing the error will be thrown, or a null will be
+ * returned. You must deal with both possibilities -- the former will happen
+ * the first time createView() is called for a class of a particular name,
+ * the latter every time there-after for that class name.
+ *
+ * @param name The full name of the class to be instantiated.
+ * @param attrs The XML attributes supplied for this instance.
+ *
+ * @return View The newly instantiated view, or null.
+ */
+ public final View createView(String name, String prefix, AttributeSet attrs)
+ throws ClassNotFoundException, InflateException {
+ Context context = (Context) mConstructorArgs[0];
+ if (context == null) {
+ context = mContext;
+ }
+ return createView(context, name, prefix, attrs);
+ }
/**
* Low-level function for instantiating a view by name. This attempts to
@@ -734,13 +767,18 @@ public abstract class LayoutInflater {
* the first time createView() is called for a class of a particular name,
* the latter every time there-after for that class name.
*
+ * @param viewContext The context used as the context parameter of the View constructor
* @param name The full name of the class to be instantiated.
* @param attrs The XML attributes supplied for this instance.
*
* @return View The newly instantiated view, or null.
*/
- public final View createView(String name, String prefix, AttributeSet attrs)
+ @Nullable
+ public final View createView(@NonNull Context viewContext, @NonNull String name,
+ @Nullable String prefix, @Nullable AttributeSet attrs)
throws ClassNotFoundException, InflateException {
+ Objects.requireNonNull(viewContext);
+ Objects.requireNonNull(name);
Constructor<? extends View> constructor = sConstructorMap.get(name);
if (constructor != null && !verifyClassLoader(constructor)) {
constructor = null;
@@ -787,22 +825,21 @@ public abstract class LayoutInflater {
}
Object lastContext = mConstructorArgs[0];
- if (mConstructorArgs[0] == null) {
- // Fill in the context if not already within inflation.
- mConstructorArgs[0] = mContext;
- }
+ mConstructorArgs[0] = viewContext;
Object[] args = mConstructorArgs;
args[1] = attrs;
- final View view = constructor.newInstance(args);
- if (view instanceof ViewStub) {
- // Use the same context when inflating ViewStub later.
- final ViewStub viewStub = (ViewStub) view;
- viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+ try {
+ final View view = constructor.newInstance(args);
+ if (view instanceof ViewStub) {
+ // Use the same context when inflating ViewStub later.
+ final ViewStub viewStub = (ViewStub) view;
+ viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+ }
+ return view;
+ } finally {
+ mConstructorArgs[0] = lastContext;
}
- mConstructorArgs[0] = lastContext;
- return view;
-
} catch (NoSuchMethodException e) {
final InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
@@ -871,6 +908,26 @@ public abstract class LayoutInflater {
}
/**
+ * Version of {@link #onCreateView(View, String, AttributeSet)} that also
+ * takes the inflation context. The default
+ * implementation simply calls {@link #onCreateView(View, String, AttributeSet)}.
+ *
+ * @param viewContext The Context to be used as a constructor parameter for the View
+ * @param parent The future parent of the returned view. <em>Note that
+ * this may be null.</em>
+ * @param name The fully qualified class name of the View to be create.
+ * @param attrs An AttributeSet of attributes to apply to the View.
+ *
+ * @return View The View created.
+ */
+ @Nullable
+ public View onCreateView(@NonNull Context viewContext, @Nullable View parent,
+ @NonNull String name, @Nullable AttributeSet attrs)
+ throws ClassNotFoundException {
+ return onCreateView(parent, name, attrs);
+ }
+
+ /**
* Convenience method for calling through to the five-arg createViewFromTag
* method. This method passes {@code false} for the {@code ignoreThemeAttr}
* argument and should be used for everything except {@code &gt;include>}
@@ -921,9 +978,9 @@ public abstract class LayoutInflater {
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
- view = onCreateView(parent, name, attrs);
+ view = onCreateView(context, parent, name, attrs);
} else {
- view = createView(name, null, attrs);
+ view = createView(context, name, null, attrs);
}
} finally {
mConstructorArgs[0] = lastContext;