Reputation: 6209
I have the following object hierarchy:
BaseMessageListFragment (abstract)
^
|
/\
/ \
/ \
/ \
/ \
/ \
/ \
/ \
| |
SwapMessageListFragment RequestMessageListFragment
Now, each of these fragments (SwapMessageListFragment
and RequestMessageListFragment
) is actually nested within another Fragment
. Taking, for example, the case of SwapMessageListFragment
, it's nested within a class called SwapDetailFragment
.
This works fine, but when I change orientation when SwapDetailFragment
is displayed, I get the following crash:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.ui.shift.ShiftDetailActivity}: android.view.InflateException: Binary XML file line #57: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.view.InflateException: Binary XML file line #57: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.app.ui.shift.fragment.SwapDetailFragment.onCreateView(SwapDetailFragment.java:559)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at com.example.app.ui.BaseActivity.onStart(BaseActivity.java:161)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
at android.app.Activity.performStart(Activity.java:6006)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.app.ui.message.fragment.BaseMessageListFragment: make sure class name exists, is public, and has an empty constructor that is public
at android.support.v4.app.Fragment.instantiate(Fragment.java:432)
at android.support.v4.app.Fragment.instantiate(Fragment.java:396)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2162)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:725)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.app.ui.shift.fragment.SwapDetailFragment.onCreateView(SwapDetailFragment.java:559)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at com.example.app.ui.BaseActivity.onStart(BaseActivity.java:161)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
at android.app.Activity.performStart(Activity.java:6006)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.InstantiationException: class com.example.app.ui.message.fragment.BaseMessageListFragment cannot be instantiated
at java.lang.Class.newInstance(Class.java:1587)
at android.support.v4.app.Fragment.instantiate(Fragment.java:421)
at android.support.v4.app.Fragment.instantiate(Fragment.java:396)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2162)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:725)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.app.ui.shift.fragment.SwapDetailFragment.onCreateView(SwapDetailFragment.java:559)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1929)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at com.example.app.ui.BaseActivity.onStart(BaseActivity.java:161)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1236)
at android.app.Activity.performStart(Activity.java:6006)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Since BaseMessageListFragment
is abstract, I'm not sure why it's trying to initialize this Fragment
. I originally had a reference to a member variable in SwapDetailFragment
called mMessageFrag
which was defined as follows:
private BaseMessageListFragment mMessageFrag;
I've tried making this a SwapMessageListFragment
instead, but with no luck. Additionally, I've tried adding default constructors to BaseMessageListFragment
(which seems a waste, since it can't be instantiated, anyway), SwapMessageListFragment
, and RequestMessageListFragment
, but, again, with no joy. Finally, I even attempted to create a newInstance()
implementation on BaseMessageListFragment
like the following:
public static BaseMessageListFragment newInstance(Class<? extends GsonBase> aBaseObjectType,
long aBaseObjectId) {
BaseMessageListFragment retVal;
Bundle args = new Bundle();
// Add arguments here
retVal.setArguments(args);
return retVal;
}
(as advised in Do fragments really need an empty constructor? ), but still with no luck.
I'm not sure what I'm doing incorrectly that causes Android to want to instantiate the base class, rather than a derived class.
EDIT:
As requested, here is a view of the fragment_swap_detail.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFF">
<RelativeLayout android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout android:id="@+id/request_header" style="@style/Material.View.Detail.Header" android:paddingTop="0dp" android:paddingBottom="0dp">
<include android:id="@+id/swap_block" layout="@layout/list_item_request_block" android:layout_width="fill_parent" android:layout_height="wrap_content" />
</FrameLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="59dp"
android:orientation="horizontal"
android:background="@drawable/button_bar_background"
android:layout_alignParentBottom="true"
android:padding="10dp">
<Button style="@style/Material.Widget.Button.Green" android:id="@+id/button_approve"
android:layout_width="0dp"
android:layout_height="38dp"
android:layout_weight="1"
android:text="Approve" />
<Button style="@style/Material.Widget.Button.Red" android:id="@+id/button_decline"
android:layout_width="0dp"
android:layout_height="38dp"
android:layout_weight="1"
android:text="Decline" />
<Button style="@style/Material.Widget.Button" android:id="@+id/button_cancel"
android:layout_width="0dp"
android:layout_height="38dp"
android:layout_weight="1"
android:text="Cancel" />
</LinearLayout>
</RelativeLayout>
<View android:layout_width="6dp" android:layout_height="match_parent" android:background="#CCCCCC" />
<ScrollView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"
android:paddingLeft="@dimen/padding_listview"
android:paddingRight="@dimen/padding_listview"
android:scrollbarStyle="outsideOverlay"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView style="@style/Material.View.Detail.Row.Header" android:id="@+id/tableheader_messages" android:text="Messages" />
<EditText android:id="@+id/swap_message"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text|textAutoCorrect|textMultiLine" />
<fragment
android:id="@+id/fragment_messages"
android:name="com.example.app.ui.message.fragment.BaseMessageListFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView style="@style/Material.View.Detail.Row.Header" android:id="@+id/tableheader_takers" android:text="Potential Takers" />
<fragment
android:id="@+id/fragment_check"
android:name="com.example.app.ui.base.list.BaseCheckListFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
Upvotes: 0
Views: 397
Reputation: 4573
I don't think you can inflate an abstract Fragment
via XML. Replace your fragment with a FrameLayout
and use FragmentManager
to load a fragment to that layout in runtime.
You should do that only once. After screen rotation your savedInstanceState
won't be null
, so your fragment will be there - FragmentManager
handles that for you.
Upvotes: 1