Having a look at this thread, I have a fundamental question.
1) Imagine I have a multi-pane layout like this one:
2) Now lets imagine that the underlying xml is like this one (for simplicity's sake most attributes are missed):
somefragment_land.xml:
<LinearLayout orientation="horizontal" ...>
<!--our side menu-->
<ListView id="@+id/menu" />
<!--our details fragment container-->
<FrameLayout id="@+id/container"/>
</LinearLayout>
3) Ok, so we have this SomeFragment class:
public class SomeFragment extends Fragment {
public static final String TAG = "TAGTAGTAG";
private static final String STATE_SELECTED_POSITION = "selected_position";
private int currentSelectedPosition;
private ListView mMenu;
private MyAdapter mAdapter;
private boolean isMultipaneMode;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isMultipaneMode = getResources().getBoolean(R.bool.show_fragment_multiplane);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION, 0);
} else if (isMultipaneMode) {
currentSelectedPosition = 0;
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int resId = isMultipaneMode ? R.layout.fragment_somefragment_land : R.layout.fragment_somefragment;
View root = inflater.inflate(resId, container, false);
mMenu = (ListView) root.findViewById(R.id.menu);
mMenu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SomeItem item = mAdapter.getItem(position);
showDetails(item);
}
});
///do some stuff creating adapter
mMenu.setAdapter(mAdapter);
if (isMultipaneMode) {
showDetails(mAdapter.getItem(currentSelectedPosition));
}
return root;
}
@Override
public void onDestroyView() {
//remove details fragment
destroyDetails();
super.onDestroyView();
}
private void destroyDetails() {
if (isMultipaneMode) {
//schedule a transaction to remove a fragment
//it will happen after SomeFragment is removed
FragmentManager fm = getFragmentManager();
Fragment fragmentByTag = fm.findFragmentByTag(FragmentDetails.TAG);
if (fragmentByTag == null) {
L.e(this.getClass(), "Details fragment removed");
return;
}
fm.beginTransaction()
.remove(fragmentByTag)
.commit();
}
}
private void showDetails(SomeItem item) {
if (isMultipaneMode) {
FragmentDetails details = new FragmentDetails();
Bundle args = new Bundle();
args.putString(FragmentDetails.ARG_ID, item.getId());
details.setArguments(args);
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment, details, FragmentDetails.TAG)
.commit()
;
} else {
ActivityDetail.launch(getActivity(), item.getTitle(), item.getType());
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (isMultipaneMode) {
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
}
}
So the logic is straightforward, show details in Fragment (for multipane mode) or start Details activity if we are running on a smartphone etc
What I want to know is - how much wrong is this approach in terms of Fragment management?
I imagine myself the following case:
SomeFragment
is added toFragmentManager
user decides to go elsewhere
Transaction_1 is started to remove
SomeFragment
this calls to
onDestroyView()
which schedules a transaction to removeDetailsFragment
Transaction_1 is complete, however, DetailsFragment is not yet removed. It possibly holds some part of SomeFragment view hierarchy in memory
Transaction_2 is started to remove DetailsFragment
Transaction_2 is complete, DetailsFragment is destroyed
???
These question marks stand for some uncertainty - have I created a memory leak? Or something worse? Any off-top-of-your-head consequences of using this approach?