Honestly, I can't help but feel that this is done merely to confuse newcomers. Most of the errors on Stack Overflow by complete Android newbies mostly stem from that they have a static inner class Fragment that they don't understand how it works, why it's there, and try to use Activities even though they don't fully understand the concept behind what is happening.
I must admit, I had trouble understanding the "PlaceholderFragment" approach too, and using static inner classes isn't really extensible at all. The first thing you'd have to do is create an actual class outside - but why do newbies have to do that?
I think this could be much more efficient if they used a project structure similar to the following simple fragment-based android project structure:
- src
- wholepackagename
- activity
- MainActivity
- fragment
- FirstFragment
- SecondFragment
- activity
- wholepackagename
- res
- layout
- values
- ...
With the code of
src/wholepackagename/activity/MainActivity:
public class MainActivity extends FragmentActivity implements FirstFragment.Callback
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
{
public void onBackStackChanged()
{
int backCount = getSupportFragmentManager().getBackStackEntryCount();
if (backCount == 0)
{
finish();
}
}
});
if (savedInstanceState == null)
{
getSupportFragmentManager().beginTransaction().add(R.id.main_container, new FirstFragment()).addToBackStack(null).commit();
}
}
@Override
public void firstFragmentCallback()
{
getSupportFragmentManager().beginTransaction().replace(R.id.main_container, new SecondFragment()).addToBackStack(null).commit();
}
}
src/wholepackagename/fragment/FirstFragment.java:
public class FirstFragment extends Fragment implements View.OnClickListener
{
private Callback callback;
private Button firstFragmentButton;
public static interface Callback
{
void firstFragmentCallback();
}
public FirstFragment()
{
super();
}
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
callback = (Callback) activity;
}
catch (ClassCastException e)
{
Log.e(getClass().getSimpleName(), activity.getClass().getSimpleName() + " must implement Callback interface!", e);
throw e;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
firstFragmentButton = (Button) rootView.findViewById(R.id.fragment_first_button);
firstFragmentButton.setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v)
{
if(v == firstFragmentButton)
{
callback.firstFragmentCallback();
}
};
}
src/wholepackagename/fragment/SecondFragment.java:
public class SecondFragment extends Fragment implements View.OnClickListener
{
private Button secondFragmentButton;
public SecondFragment()
{
super();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_second, container, false);
secondFragmentButton = (Button) rootView.findViewById(R.id.fragment_second_button);
secondFragmentButton.setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v)
{
if(v == secondFragmentButton)
{
Toast.makeText(getActivity(), "This is an example!", Toast.LENGTH_LONG).show();
}
};
}
Android-Manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wholepackagename"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="wholepackagename.activity.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
res/layout/activity_main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
res/layout/fragment_first.xml:
<?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" >
<Button
android:id="@+id/fragment_first_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/first_button" />
</RelativeLayout>
res/layout/fragment_second.xml:
<?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" >
<Button
android:id="@+id/fragment_second_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/second_button" />
</RelativeLayout>
res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Application name</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="first_button">First Button</string>
<string name="second_button">Second Button</string>
</resources>
To me, it seems that the static inner class Fragment doesn't really support any kind of maintainability, it's hard to see what is going on, and the overall functionality is not obvious as the Activity and Fragment (display of fragment and logic) are mixed together, which makes it hard to see and oversee for a newbie.
I believe it would provide an easier entry into developing for the Android platform to have an example like above. Are there any benefits to the current approach, providing a static inner class as a Fragment?