Reputation: 299
I am planning an messenger app, which consist of several areas:
On a Smartphone, there should be only one activty at a time, but the tablet should have a sidebar with shortcuts (In conversation view showing the contact list, in settings showing a list of setting categories).
As far as my understanding is, those areas will be fragments, which get inserted into one or more activities.
So I started creating an activity with the following layout (res/main.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="vertical" >
<fragment
android:id="@id/main_fragment_focus"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
and the corresponding tablet layout: (layout-large-land/main.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" >
<fragment
android:id="@id/main_fragment_sidebar"
android:layout_width="@dimen/main_sidebar_width"
android:layout_height="match_parent" />
<fragment
android:id="@id/main_fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
So far, so good. At least as far as I thought. So I created a simple activity; I am using ActionBarSherlock, because I want to provide compatibility with API Level 5+:
package com.pm.messenger;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class PMMessengerActivity extends SherlockFragmentActivity {
// -------------------------------------------------------------------------
FragmentManager fragmentManager = null;
// -------------------------------------------------------------------------
public void onCreate(Bundle savedInstanceState) {
// ---------------------------------------------------------------------
super.onCreate(savedInstanceState);
// ---------------------------------------------------------------------
fragmentManager = getSupportFragmentManager();
// ---------------------------------------------------------------------
if (savedInstanceState == null) {
// -----------------------------------------------------------------
// -----------------------------------------------------------------
}
else {
// -----------------------------------------------------------------
// -----------------------------------------------------------------
}
// ---------------------------------------------------------------------
Log.d(getClass().getSimpleName(), "no problem before setContentView");
setContentView(R.layout.main);
Log.d(getClass().getSimpleName(), "no problem after setContentView");
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
}
After executing this, my app crashes immediately. First I thought, this happens because I didn't provide any FragmentManager-FragmentTransactions, but then I noticed (after inserting the Log.d-Lines) that the crash happens while calling SetContentView.
LogCat-Output:
01-24 16:58:26.728: I/ActivityManager(667): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.pm.messenger/.pmMessengerActivity bnds=[912,542][1008,638]} from pid 877
01-24 16:58:26.748: D/dalvikvm(26431): Late-enabling CheckJNI
01-24 16:58:26.758: I/ActivityManager(667): Start proc com.pm.messenger for activity com.pm.messenger/.pmMessengerActivity: pid=26431 uid=10009 gids={3003, 1015}
01-24 16:58:26.778: E/jdwp(26431): Failed sending reply to debugger: Broken pipe
01-24 16:58:26.778: D/dalvikvm(26431): Debugger has detached; object registry had 1 entries
01-24 16:58:26.788: D/OpenGLRenderer(877): Flushing caches (mode 1)
01-24 16:58:26.828: D/pmMessengerActivity(26431): no problem before setContentView
01-24 16:58:26.858: D/AndroidRuntime(26431): Shutting down VM
01-24 16:58:26.858: W/dalvikvm(26431): threadid=1: thread exiting with uncaught exception (group=0x40a3e1f8)
01-24 16:58:26.868: D/OpenGLRenderer(877): Flushing caches (mode 0)
01-24 16:58:26.868: E/AndroidRuntime(26431): FATAL EXCEPTION: main
01-24 16:58:26.868: E/AndroidRuntime(26431): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pm.messenger/com.pm.messenger.pmMessengerActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.access$600(ActivityThread.java:123)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.os.Handler.dispatchMessage(Handler.java:99)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.os.Looper.loop(Looper.java:137)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.main(ActivityThread.java:4424)
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.reflect.Method.invokeNative(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.reflect.Method.invoke(Method.java:511)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-24 16:58:26.868: E/AndroidRuntime(26431): at dalvik.system.NativeStart.main(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class fragment
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:251)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.actionbarsherlock.internal.ActionBarSherlockNative.setContentView(ActionBarSherlockNative.java:119)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:262)
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.pm.messenger.pmMessengerActivity.onCreate(pmMessengerActivity.java:48)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.Activity.performCreate(Activity.java:4465)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
01-24 16:58:26.868: E/AndroidRuntime(26431): ... 11 more
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: java.lang.NullPointerException: name == null
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.VMClassLoader.findLoadedClass(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:354)
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.loadClass(ClassLoader.java:491)
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.Fragment.instantiate(Fragment.java:381)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.Fragment.instantiate(Fragment.java:359)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:262)
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:669)
01-24 16:58:26.868: E/AndroidRuntime(26431): ... 22 more
01-24 16:58:26.868: W/ActivityManager(667): Force finishing activity com.pm.messenger/.pmMessengerActivity
01-24 16:58:27.408: W/ActivityManager(667): Activity pause timeout for ActivityRecord{410d8c98 com.pm.messenger/.pmMessengerActivity}
Now I think, this crash is because I didn't provide any fragment classes statically in the XML, BUT I don't want to use this, I want to achive this in a dynamical way.
When I have to provide classes statically in the XML, I think I also need multiple Activitiys (like LoginActivity, SignupActivity, ContactListActivity, ConversationActivity) but... stop, this couldn't be right, because then my fragments loose their right to exist imho.
As far as my understanding is, a fragment is a lonestanding part of my app, implementing an area of features like the activitys did back in the day; those will be embedded into a container activity, which manages the backstack.
So where's the fault in my logic? Should I use a Layout with FrameView's instead of Fragments? Don't know.
Also I don't find any good, understandable, well-documented ressources for the dynamical fragment management.
Upvotes: 1
Views: 1570
Reputation: 4120
Your specific error is due to the fact that you are trying to inflate a fragment that does not exist, apparently. For dynamic fragments, you should place a FrameLayout in your static layout and put the fragments into those frames at runtime. Here's an example of a layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<View
android:id="@+id/anchor"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerInParent="true" />
<FrameLayout
android:id="@+id/top_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_above="@+id/anchor"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/anchor">
</FrameLayout>
<FrameLayout
android:id="@+id/top_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_above="@+id/anchor"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/anchor">
</FrameLayout>
<FrameLayout
android:id="@+id/bottom_left"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_below="@+id/anchor"
android:layout_toLeftOf="@+id/anchor">
</FrameLayout>
<FrameLayout
android:id="@+id/bottom_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/anchor"
android:layout_toRightOf="@+id/anchor">
</FrameLayout>
</RelativeLayout>
This happens to put four FrameLayouts of equal size in a grid. You can add a fragment at runtime with this:
Fragment levelsF = Fragment.instantiate(this,
LevelsFragment.class.getName());
Fragment waveF = Fragment.instantiate(this,
WaveFragment.class.getName());
Fragment lightF = Fragment.instantiate(this,
LightPlayerFragment.class.getName());
Fragment keyboardF = Fragment.instantiate(this,
KBFragment.class.getName());
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.top_left, levelsF);
ft.add(R.id.top_right, waveF);
ft.add(R.id.bottom_left, lightF);
ft.add(R.id.bottom_right, keyboardF);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
getSupportFragmentManager().executePendingTransactions();
If you don't want static fragments, don't reference them in xml at all.
Upvotes: 1
Reputation: 2100
Android have a wonderful documentation for its APIs. It clearly explains the lifecycle and the methods of Fragment class. Hope this helps. Fragments Documentation
Upvotes: 0