1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.app;
17 
18 import com.android.ide.common.rendering.api.LayoutlibCallback;
19 import com.android.layoutlib.bridge.android.BridgeContext;
20 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
21 
22 import android.content.Context;
23 import android.os.Bundle;
24 
25 /**
26  * Delegate used to provide new implementation of a select few methods of {@link Fragment}
27  *
28  * Through the layoutlib_create tool, the original  methods of Fragment have been replaced
29  * by calls to methods of the same name in this delegate class.
30  *
31  * The methods being re-implemented are the ones responsible for instantiating Fragment objects.
32  * Because the classes of these objects are found in the project, these methods need access to
33  * {@link LayoutlibCallback} object.
34  */
35 public class Fragment_Delegate {
36     /**
37      * Like {@link #instantiate(Context, String, Bundle)} but with a null
38      * argument Bundle.
39      */
40     @LayoutlibDelegate
instantiate(Context context, String fname)41     /*package*/ static Fragment instantiate(Context context, String fname) {
42         return instantiate(context, fname, null);
43     }
44 
45     /**
46      * Create a new instance of a Fragment with the given class name.  This is
47      * the same as calling its empty constructor.
48      *
49      * @param context The calling context being used to instantiate the fragment.
50      * This is currently just used to get its ClassLoader.
51      * @param fname The class name of the fragment to instantiate.
52      * @param args Bundle of arguments to supply to the fragment, which it
53      * can retrieve with {@link Fragment#getArguments()}.  May be null.
54      * @return Returns a new fragment instance.
55      * @throws Fragment.InstantiationException If there is a failure in instantiating
56      * the given fragment class.  This is a runtime exception; it is not
57      * normally expected to happen.
58      */
59     @LayoutlibDelegate
instantiate(Context context, String fname, Bundle args)60     /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) {
61         try {
62             if (context instanceof BridgeContext) {
63                 BridgeContext bc = (BridgeContext) context;
64                 Fragment f = (Fragment) bc.getLayoutlibCallback().loadView(fname,
65                         new Class[0], new Object[0]);
66 
67                 if (args != null) {
68                     args.setClassLoader(f.getClass().getClassLoader());
69                     f.mArguments = args;
70                 }
71                 return f;
72             }
73 
74             return null;
75         } catch (Exception e) {
76             throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
77                     + ": make sure class name exists, is public, and has an"
78                     + " empty constructor that is public", e);
79         }
80     }
81 }
82