Apr 16

I’m currently in the process of making the landscape support in LoanShark more robust. When in portrait mode, the main activity displays a list of loans, while the view loan activity, opened by selecting an item from the list, displays the selected loans’ details. In landscape orientation both views are visible. These are all implemented using fragments, i.e. the activities themselves only provide the layout to glue the fragments together.

When holding the device in portrait mode, the loan view displays loan details using the same fragment class as is used on the right-hand side in landscape orientation. When the user is viewing a loan in portrait (view loan activity), and rotates the device to landscape (to main activity), the same loan is displayed.

The problem I’ve come across is that since fragment objects belong to a single Activity (stored in the Activity object’s own FragmentManager instance), there’s no way to reuse the fragment that’s seen in portrait mode of the view loan activity on the right-hand side of the landscape layout in the main activity. The reason is that when the user rotates from portrait to landscape, the activity hosting the loan details is destroyed, which in turn destroys the fragment as well.

To keep my fragment implementations modular (to break direct dependencies between them), I’ve utilized callbacks to the hosting activity class when loaders have finished their jobs. This way I’m able to know e.g. when a loan’s details have been finished so that the fragment can be created.

My initial implementation (and the one being used in version 2.2.0) is that the old fragment that was created when in landscape mode is displayed briefly before being replaced with the loan that was selected in portrait mode. This is clearly suboptimal because there’s a clear visual anomaly, however brief, when rotating the device. I considered patching the problem by hiding the existing fragment in landscape,  thus preventing the old fragment from being shown before fading in the fragment when then the new loan would have been loaded. That wouldn’t have been a solution I would’ve been satisfied with, so clearly more thinking was needed.

When a loan has been loaded in portrait mode and is about to be displayed in the view loan activity, I store the loan data in the main activity as well (and make sure it’s saved in onSaveInstanceState() in case the activity is destroyed while viewing the loan data). Then, if the user rotates the device to landscape, I check if the view loan fragment already exists (in case the device has been in landscape mode previously, it does). In such a case, I set the selected loan’s data to the existing fragment. When the activity’s onCreate() finishes, the fragment’s onCreateView() is called, and it’s there that the loan data can then be reused.

Nothing of this sort is mentioned in documentation concerning fragments. Also, it’s quite difficult to find solutions to fragment problems by googling them; all you seem to get is countless beginner tutorials on how to use fragments. I came across this solution after spending a couple of nights figuring out how the fragment management works internally, and from there I had an idea how to go on about solving the problem.

Leave a Reply

preload preload preload