title: Stuck with porting from activity to fragment
body: <p>It's now one week exactly that I try to port a simple activity-based app to fragments. I'm totally stuck.</p>
  
  <p>This beast is a simple List, Details, Add/Edit app with contextmenu and optionmenus. I tried to make it right: Fragments and activities each in their own file, using the v4 support-package for phone and tablet, fragments do everything a re-usable fragment should do and callbacks (lots of them) fly around to inform activities and fragments about what to do. Converting from SQLiteOpenHelper to ContentProvider, converting from optionmenu to actionbarmenu, and, and, and, ... (nearly everything I used is deprecated now).</p>
  
  <p>It's horrible. My simple and small working activity-based app has nearly 3 times the size now and lots of things are not working yet.</p>
  
  <p>If it's required I can add my code here - but it's a lot of stuff (you've been warned).</p>
  
  <p>My question: Is there somebody willing to share a complete example with List, Details <strong>AND</strong> Add/Edit? This example should use seperate files for Fragments and Activities (not that all-in-one package from Google).</p>
  
  <p>Please don't down-vote. I really would like to see how to make it right.</p>
  
  <p>Many thanks in advance.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Here's the starting activity with it's two layouts (res/layout for phone and res/layout-large-land for tablets) and the contextmenu:</p>
  
  <pre><code>public class ActivityList extends FragmentActivity implements FragmentList.MyContextItemSelectedListener,
                                                        FragmentList.MyDeleteListener,
                                                        FragmentList.MyListItemClickListener,
                                                        FragmentList.MyOptionsItemSelectedListener,
                                                        FragmentDetails.MyDeleteListener,
                                                        FragmentDetails.MyOptionsItemSelectedListener {
  
      @Override
      public void myContextItemSelected(final int action, final long id) {
          if (action == R.id.men_add) {
              processEdit(0);
          } else if (action == R.id.men_delete) {
              processUpdateList();
          } else if (action == R.id.men_details) {
              processDetails(id);
          } else if (action == R.id.men_edit) {
              processEdit(id);
          }
      }
  
      @Override
      public void myDelete(final long id) {
          processUpdateList();
      }
  
      @Override
      public void myListItemClick(final long id) {
          processDetails(id);
      }
  
      @Override
      public void myOptionsItemSelected(final int action) {
          myOptionsItemSelected(action, 0);
      }
  
      @Override
      public void myOptionsItemSelected(final int action, final long id) {
          if (action == R.id.men_add) {
              processEdit(0);
          } else if (action == R.id.men_edit) {
              processEdit(id);
          } else if (action == R.id.men_preferences) {
              processPreferences();
          }
      }
  
      @Override
      protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
          processUpdateList();
      }
  
      @Override
      public void onCreate(final Bundle bundle) {
          super.onCreate(bundle);
  
          setContentView(R.layout.activitylist);
      }
  
      private void processEdit(final long id) {
          Intent intent = new Intent(this, ActivityEdit.class);
          intent.putExtra("ID", id);
          startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
      }
  
      private void processDetails(final long id) {
          if (Tools.isXlargeLand(getApplicationContext())) {
              Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.right);
              if (fragment == null ||
                      (fragment instanceof FragmentDetails &amp;&amp; ((FragmentDetails) fragment).getCurrentId() != id)) {
                  fragment = new FragmentDetails(id);
  
                  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                  transaction.replace(R.id.right, fragment);
                  transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                  transaction.commit();
              }
          } else {
              Intent intent = new Intent(this, ActivityDetails.class);
              intent.putExtra("ID", id);
              startActivityForResult(intent, MyConstants.DLG_TABLE1SHOW);
          }
      }
  
      private void processPreferences() {
          Intent intent = new Intent(this, MyPreferenceActivity.class);
          startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
      }
  
      private void processUpdateList() {
          // TODO:
      }
  }
  
  &lt;LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="horizontal" &gt;
  
      &lt;fragment 
          class="com.test.app.FragmentList"
          android:id="@+id/fragmentlist"
          android:layout_height="match_parent"
          android:layout_width="match_parent"
          android:name="com.test.app.FragmentList" /&gt;
  &lt;/LinearLayout&gt;
  
  &lt;LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="horizontal" &gt;
  
      &lt;fragment 
          class="com.test.app.FragmentList"
          android:id="@+id/fragmentlist"
          android:layout_height="match_parent"
          android:layout_weight="1"
          android:layout_width="0dip"
          android:name="com.test.app.FragmentList" /&gt;
  
      &lt;FrameLayout
          android:id="@+id/right"
          android:layout_height="match_parent"
          android:layout_weight="2"
          android:layout_width="0dip" /&gt;
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>Here's the ListFragment with it's row layout, optionsmenu and contextmenu:</p>
  
  <pre><code>public class FragmentList extends ListFragment implements LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
  
      private SimpleCursorAdapter           adapter;
      private AlertDialog                   alertDialog;
      private Context                       context;
      private MyContextItemSelectedListener contextItemSelectedListener;
      private MyDeleteListener              deleteListener;
      private long                          id;
      private MyListItemClickListener       listItemClickListener;
      private ListView                      listView;
      private MyOptionsItemSelectedListener optionsItemSelectedListener;
  
      public interface MyContextItemSelectedListener {
          public void myContextItemSelected(int action, long id);
      }
  
      public interface MyDeleteListener {
          public void myDelete(long id);
      }
  
      public interface MyListItemClickListener {
          public void myListItemClick(long id);
      }
  
      public interface MyOptionsItemSelectedListener {
          public void myOptionsItemSelected(int action);
      }
  
      @Override
      public void onActivityCreated(final Bundle bundle) {
          super.onActivityCreated(bundle);
  
          context = getActivity().getApplicationContext();
  
          listView = getListView();
  
          getActivity().getSupportLoaderManager().initLoader(MyConstants.LDR_TABLE1LIST, null, this);
  
          adapter = new SimpleCursorAdapter(context,
                                            R.layout.fragmentlist_row,
                                            null,
                                            new String[] { Table1.DESCRIPTION },
                                            new int[] { R.id.fragmentlist_row_description },
                                            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
          setListAdapter(adapter);
          setListShown(false);
  
          registerForContextMenu(listView);
  
          if (bundle != null &amp;&amp; bundle.containsKey("ID")) {
              id = bundle.getLong("ID");
              listItemClickListener.myListItemClick(id);
          }
  
          if (Tools.isXlargeLand(context)) {
              listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
          }
  
          setHasOptionsMenu(true);
      }
  
      @Override
      public void onAttach(final Activity activity) {
          super.onAttach(activity);
  
          // Reduced: Check for implemented listeners
      }
  
      @Override
      public boolean onContextItemSelected(final MenuItem menuItem) {
          AdapterContextMenuInfo adapterContextMenuInfo = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
  
          final long id = adapterContextMenuInfo.id;
  
          if (menuItem.getItemId() == R.id.men_delete) {
              processAlertDialog(id);
              return true;
          } else {
              contextItemSelectedListener.myContextItemSelected(menuItem.getItemId(), adapterContextMenuInfo.id);
          }
  
          return super.onContextItemSelected(menuItem);
      }
  
      @Override
      public void onCreateContextMenu(final ContextMenu contextMenu, final View view, final ContextMenuInfo contextMenuInfo) {
          super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
  
          if (view.getId() == android.R.id.list) {
              getActivity().getMenuInflater().inflate(R.menu.fragmentlist_context, contextMenu);
          }
      }
  
      @Override
      public Loader&lt;Cursor&gt; onCreateLoader(final int id, final Bundle bundle) {
          MyCursorLoader loader = null;
  
          switch (id) {
              case MyConstants.LDR_TABLE1LIST:
                  loader = new MyCursorLoader(context,
                                              MySQLiteOpenHelper.TABLE1_FETCH,
                                              null);
                  break;
          }
  
          return loader;
      }
  
      @Override
      public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
          super.onCreateOptionsMenu(menu, menuInflater);
  
          menu.clear();
  
          menuInflater.inflate(R.menu.fragmentlist, menu);
      }
  
      @Override
      public void onListItemClick(final ListView listView, final View view, final int position, final long id) {
          super.onListItemClick(listView, view, position, id);
  
          this.id = id;
  
          if (Tools.isXlargeLand(context)) {
              listView.setItemChecked(position, true);
          }
  
          listItemClickListener.myListItemClick(id);
      }
  
      @Override
      public void onLoaderReset(final Loader&lt;Cursor&gt; loader) {
          adapter.swapCursor(null);
      }
  
      @Override
      public void onLoadFinished(final Loader&lt;Cursor&gt; loader, final Cursor cursor) {
          adapter.swapCursor(cursor);
  
          setListShown(true);
      }
  
      @Override
      public boolean onOptionsItemSelected(final MenuItem menuItem) {
          optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId());
  
          return super.onOptionsItemSelected(menuItem);
      }
  
      @Override
      public void onSaveInstanceState(final Bundle bundle) {
          super.onSaveInstanceState(bundle);
  
          bundle.putLong("ID", id);
      }
  
      private void processAlertDialog(final long id) {
          final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
          alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
  
              @Override
              public void onClick(final DialogInterface dialogInterface, final int which) {
                  dialogInterface.dismiss();
              }
          } );
          alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  
              @Override
              public void onClick(final DialogInterface dialogInterface, final int which) {
                  MyApplication.getSqliteOpenHelper().deleteTable1(id);
  
                  alertDialog.dismiss();
  
                  deleteListener.myDelete(id);
              }
          } );
          alertDialogBuilder.setCancelable(false);
          alertDialogBuilder.setMessage(R.string.txt_reallydelete);
  
          alertDialog = alertDialogBuilder.create();
          alertDialog.show();
      }
  }
  
  &lt;LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="wrap_content"
      android:layout_width="fill_parent"
      android:orientation="horizontal"
      android:paddingBottom="2dip"
      android:paddingTop="2dip" &gt;
  
      &lt;TextView
          style="@style/TextViewLarge"
          android:id="@+id/fragmentlist_row_description"
          android:textStyle="bold" /&gt;
  &lt;/LinearLayout&gt;
  
  
  &lt;menu
      xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_add"
          android:id="@+id/men_add"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_add" /&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_preferences"
          android:id="@+id/men_preferences"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_preferences" /&gt;
  &lt;/menu&gt;
  
  &lt;menu
      xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  
      &lt;item
          android:id="@+id/men_details"
          android:title="@string/txt_details" /&gt;
  
      &lt;item
          android:id="@+id/men_edit"
          android:title="@string/txt_edit" /&gt;
  
      &lt;item
          android:id="@+id/men_delete"
          android:title="@string/txt_delete" /&gt;
  &lt;/menu&gt;
  </code></pre>
  
  <p>This is DetailsActivity:</p>
  
  <pre><code>public class ActivityDetails extends FragmentActivity implements FragmentDetails.MyDeleteListener, 
                                                                      FragmentDetails.MyOptionsItemSelectedListener {
  
      private long id;
  
      @Override
      public void myDelete(final long id) {
          setResult(RESULT_OK);
          finish();
      }
  
      @Override
      public void myOptionsItemSelected(final int action, final long id) {
          if (action == R.id.men_add) {
              processEdit(0);
          } else if (action == R.id.men_edit) {
              processEdit(id);
          } else if (action == R.id.men_preferences) {
              processPreferences();
          }
      }
  
      @Override
      protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
          if (requestCode == MyConstants.DLG_PREFERENCES || requestCode == MyConstants.DLG_TABLE1EDIT) {
              finish();
  
              startActivity(getIntent()); 
          }
      }
  
      @Override
      protected void onCreate(final Bundle bundle) {
          super.onCreate(bundle);
  
          if (bundle != null) {
              if (bundle.containsKey("ID")) {
                  id = bundle.getLong("ID");
              }
          } else {
              Bundle bundleExtras = getIntent().getExtras();
              if (bundleExtras != null) {
                  id = bundleExtras.getLong("ID");
              }
  
              processDetails(id);
          }
      }
  
      @Override
      public void onSaveInstanceState(final Bundle bundle) {
          super.onSaveInstanceState(bundle);
  
          bundle.putLong("ID", id);
      }
  
      private void processDetails(final long id) {
          FragmentDetails fragment = new FragmentDetails(id);
  
          FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
          transaction.replace(android.R.id.content, fragment);
          transaction.commit();
      }
  
      private void processEdit(final long id) {
          Intent intent = new Intent(this, ActivityEdit.class);
          intent.putExtra("ID", id);
          startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
      }
  
      private void processPreferences() {
          Intent intent = new Intent(this, MyPreferenceActivity.class);
          startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
      }
  }
  </code></pre>
  
  <p>Here's the DetailsFragment with Layout and Menu:</p>
  
  <pre><code>public class FragmentDetails extends Fragment {
  
      private AlertDialog                   alertDialog;
      private MyDeleteListener              deleteListener;
      private long                          id;
      private MyOptionsItemSelectedListener optionsItemSelectedListener;
      private TextView                      textViewDescription;
      private TextView                      textViewId;
  
      public FragmentDetails() {
          id = 0;
      }
  
      public FragmentDetails(final long id) {
          this.id = id;
      }
  
      public long getCurrentId() {
          return id;
      }
  
      public interface MyDeleteListener {
          public void myDelete(long id);
      }
  
      public interface MyOptionsItemSelectedListener {
          public void myOptionsItemSelected(int action, long id);
      }
  
      @Override
      public void onActivityCreated(final Bundle bundle) {
          super.onActivityCreated(bundle);
  
          if (bundle != null &amp;&amp; bundle.containsKey("ID")) {
              id = bundle.getLong("ID");
          }
  
          setHasOptionsMenu(true);
      }
  
      @Override
      public void onAttach(final Activity activity) {
          super.onAttach(activity);
  
          // Reduced
      }
  
      @Override
      public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
          super.onCreateOptionsMenu(menu, menuInflater);
  
          menu.clear();
  
          menuInflater.inflate(R.menu.fragmentdetails, menu);
      }
  
      @Override
      public View onCreateView(final LayoutInflater inflater, final ViewGroup viewGroup, final Bundle bundle) {
          View view = inflater.inflate(R.layout.fragmentdetails, null);
  
          textViewDescription = (TextView) view.findViewById(R.id.tv_description);
          textViewId = (TextView) view.findViewById(R.id.tv_id);
  
          if (id != 0) {
              Table1 table1;
              if ((table1 = MyApplication.getSqliteOpenHelper().getTable1(id)) != null) {
                  textViewDescription.setText(Tools.defaultString(table1.getDescription()));
                  textViewId.setText(Tools.defaultString(String.valueOf(table1.getId())));
              }
          }
  
          return view;
      }
  
      @Override
      public boolean onOptionsItemSelected(final MenuItem menuItem) {
          if (menuItem.getItemId() == R.id.men_delete) {
              processAlertDialog(id);
              return true;
          } else {
              optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId(), id);
          }
  
          return super.onOptionsItemSelected(menuItem);
      }
  
      @Override
      public void onSaveInstanceState(final Bundle bundle) {
          super.onSaveInstanceState(bundle);
  
          bundle.putLong("ID", id);
      }
  
      private void processAlertDialog(final long id) {
          final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
          alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
  
              @Override
              public void onClick(final DialogInterface dialogInterface, final int which) {
                  alertDialog.dismiss();
                  alertDialog = null;
              }
          } );
          alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  
              @Override
              public void onClick(final DialogInterface dialogInterface, final int which) {
                  MyApplication.getSqliteOpenHelper().deleteTable1(id);
  
                  alertDialog.dismiss();
                  alertDialog = null;
  
                  deleteListener.myDelete(id);
              }
          } );
          alertDialogBuilder.setCancelable(false);
          alertDialogBuilder.setMessage(R.string.txt_reallydelete);
  
          alertDialog = alertDialogBuilder.create();
          alertDialog.show();
      }
  }
  
  &lt;LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="wrap_content"
      android:layout_width="match_parent"
      android:orientation="vertical" &gt;
  
      &lt;LinearLayout
          android:layout_height="wrap_content"
          android:layout_width="match_parent"
          android:orientation="horizontal" &gt;
  
          &lt;TextView
              style="@style/TextViewStandard"
              android:layout_weight="1" 
              android:text="@string/txt_id" /&gt;
  
          &lt;TextView
              style="@style/TextViewStandard"
              android:id="@+id/tv_id"
              android:layout_weight="1" /&gt;
      &lt;/LinearLayout&gt;
  
      &lt;LinearLayout
          android:layout_height="wrap_content"
          android:layout_width="match_parent"
          android:orientation="horizontal" &gt;
  
          &lt;TextView
              style="@style/TextViewStandard"
              android:layout_weight="1" 
              android:text="@string/txt_description" /&gt;
  
          &lt;TextView
              style="@style/TextViewStandard"
              android:id="@+id/tv_description"
              android:layout_weight="1" /&gt;
      &lt;/LinearLayout&gt;
  &lt;/LinearLayout&gt;
  
  &lt;menu
      xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_add"
          android:id="@+id/men_add"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_add" /&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_edit"
          android:id="@+id/men_edit"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_edit" /&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_delete"
          android:id="@+id/men_delete"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_delete" /&gt;
  
      &lt;item
          android:icon="@drawable/ic_menu_preferences"
          android:id="@+id/men_preferences"
          android:showAsAction="ifRoom|withText"
          android:title="@string/txt_preferences" /&gt;
  &lt;/menu&gt;
  </code></pre>
  
  <p>I don't post the EditActivity because it's simply an FragmentActivity without a Fragment.</p>