Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which one to use NavUtils.navigateUpFromSameTask() vs. onBackPressed()

Tags:

android

I have two activities A and B. The A has a ListFragment which uses LoaderManager, whereas B activity shows a details about the item selected in the A's ListFragment. I've just noticed that when I use a back button to get from the B back to the A, the position in the ListFragment preserve, but when I use the up button (left-point caret) in the action bar, the A activity is recreated and thus position in list view is lost.

I would like fix this issue, but I am not sure about the best way how to do it right.

I come up with this solutions:

a) Use onBackPressed()

Replace the default implementation for the android.R.id.home (the up action bar button) in the B activity, and instead of the NavUtils.navigateUpFromSameTask(this) function call the onBackPressed() activity method. I've tested it and it works.

b) Keep use NavUtils.navigateUpFromSameTask(this)

But implement the onSaveInstanceState and restore listView position during onCreate method of the ListFragment used by the A activity. (I've not tested this approach yet)


Which of this solutions is better? Or is there any other (much more better) solution?

Solution a) is pretty simple and straight forward, but b) is probably better because the default implementation of the up caret is used.

Any ideas are welcome. Thanks.

like image 522
Tomáš Mlčoch Avatar asked Sep 19 '13 22:09

Tomáš Mlčoch


1 Answers

Solution c is the correct option. First, though, an explanation of the problem with solution a.

There is absolutely no point in having two back buttons in your Activity. Furthermore, option a actually breaks the up button. The point of the up button is to provide a way for users to stay within your app when they have landed in your app from an outside source. For example, if you land on activity B from an outside activity C and if you are using your option a, then pressing "up" in activity B will result in activity C being shown. The behavior you would want would be for activity A to be shown.

As you can see, solution b is on the right track. You definitely want to go up to A and not back to C. However, simply storing the state in onSaveInstanceState will not cause the state to be retained. This is because onSaveInstanceState only gets called if your application may be killed by the system. It is not guaranteed to be called if your application was destroyed manually, and it certainly won't be called when a new instance of your Activity is created. If the Intent starts a new activity, then it will not have its state restored from the other activity.

There solution, then, is that you must write anything persistent to a shared preference file (or a custom persistent alternative). When doing this you can guarantee that all instances of an Activity share the same state across multiple tasks so long as their onResume (or wherever you restore state) is called. OR:

If you know exactly how you want your navigation to work, you can avoid writing everything to persistent state by using a combination of Intent flags and Activity task affinities. If you want to use the same activity as up even if you navigate into the application from an outside source, then you can leave your Activity A's affinity as default (linked to the application) and use something like Intent.FLAG_ACTIVITY_CLEAR_TOP.

Personally, I'd try the Intent flag approach first and failing that fall back to writing the state persistently. You just don't really want scroll location sitting on persistent storage if you can avoid it..

like image 87
dcow Avatar answered Sep 26 '22 19:09

dcow