85

I know, that I get the same result with both code snippets

finish();
startActivity(newActivity);

and

startActivity(newActivity);
finish();

I'd like to know your opinion, if there is a big difference between them. Is one better than the other? If so, why?

benomatis
  • 5,536
  • 7
  • 36
  • 59
Tima
  • 12,765
  • 23
  • 82
  • 125

7 Answers7

62

When you do startActivity(), all that does is post your intent in a queue of events. The actual starting of the activity happens asynchronously in the near future. So I don't see a big difference between the two.

Emmanuel
  • 16,791
  • 6
  • 48
  • 74
  • 1
    it sounds sensibly to me as well – Tima Nov 15 '10 at 16:06
  • 7
    The animation is different for me. See my answer below. – Monstieur May 21 '14 at 09:02
  • but approach is just completely WRONG.. There are flags (for intent as well in manifest) which actually exist for this use cases. – Ewoks Jun 02 '15 at 13:04
  • @Ewoks please go head, what do means, which flags ? – Anthony Sep 21 '15 at 09:54
  • Is it possible that finish() leads to destruction of current activity instance before startActivity(in); happens? – Weishi Z Sep 02 '16 at 08:53
  • @WeishiZeng That would happen anyway because startActivity() isn't doing anything besides posting the intent to a queue; the real starting happens later. – Emmanuel Sep 03 '16 at 03:30
  • @Emmanuel It comes to me the understanding of `destruction of instance`. If it means destroy the activity object (e.g. like garbage collection), then `startActivity(in)` wouldn't run as they are the activity object's methods/variables. But I suppose it only removes the activity object from task queue, so hitting back button on UI won't go back to that activity. – Weishi Z Sep 03 '16 at 04:13
  • 1
    In my case it makes a complete difference. Activity A (singleTop) calles activity B (default). If i do from B -> startActivity and finish, then A onCreate is called. On the other hand, if i do from B -> finish and startActivity, then A onNewIntent is called. HUGE difference depending on the activity launchMode defined! – Kaizie Feb 12 '17 at 09:13
  • 5
    There is actually a big difference in app task behavior. I elaborated the matter in a separate answer. – Vit Khudenko Jan 20 '20 at 16:21
28

The animation is clearly different (at least on 4.1 onwards). Calling finish() first starts to fade away the first activity earlier and you can briefly see a black background before the new activity fades in. Calling startActivity() first fades in the new activity on top of the old one and the black background is not visible.

Monstieur
  • 7,992
  • 10
  • 51
  • 77
25

There is an important difference in application task behavior depending on the order of startActivity() and finish() invocations.

The case I am describing is scoped only to the situation when the current activity (the one being stopped) is the only one in the task.

Normally you would expect that the starting intent (the intent you create to start another activity) is not altered by the system. And that is not the case if finish() is called on the last activity in the task before calling startActivity().

In this case the ActivityManager, a system component, while executing the startActivity() adds Intent.FLAG_ACTIVITY_NEW_TASK flag to your intent.

When this happens, then one may notice a log entry in the LogCat similar to this one:

W/ActivityManager: startActivity called from finishing ActivityRecord{4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 f}; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { cmp=com.foo.bar/com.foo.bar.MainActivity }

And this is the turning point from which (under some conditions) things may go wrong.

To sum up, if you want to be on a safe side (rather than experience unexpected side effects of the FLAG_ACTIVITY_NEW_TASK being added to the intent), then the order must be:

  • startActivity()
  • finish()

Demo project.

Screen recordings:

Vit Khudenko
  • 28,288
  • 10
  • 63
  • 91
  • Looking at the source code, Activity.startActivity() ultimately calls ActivityThread.sendActivityResult() which in turn calls scheduleSendResult() which just adds the activity to a queue. A thread will process it later. On the other hand finish() calls ActivityManagerNative.finishActivity() which ends the activity right away. – Emmanuel Jan 21 '20 at 21:05
  • @Emmanuel, I am failing to figure out whether your statement relates to the issue I described. :) – Vit Khudenko Jan 22 '20 at 10:11
  • 1
    Only this answer clarified the observed behavior for me. When calling finish before startActivity, was facing very random issues in layout of the next activity. – Amit May 05 '22 at 16:21
9

In addition to the Emmanuels answer:

Both methods startActivity and finish will be scheduled after the end of the invoking method, since both are processed by the UI thread.

scheffield
  • 6,618
  • 2
  • 30
  • 31
7

I would do the second choice, I'm not backing this on anything that I have looked up from official sources, but, it makes more sense to launch the new activity before you call finish, that way the new activity pops up via an intent, and the now background activity can call all its cleaning up methods.

If you were to do it the other way around, maybe the intent wont have time to fire before the cleaning up is done. I.e. will the activity call startActivity() after the finish() call?

I hope you understand what I'm trying to state, I would do the second option just to be safe.

blindstuff
  • 18,298
  • 10
  • 47
  • 48
  • Yes, i understood your idea. It sounds logical. But I cann't imagine me, when this situation could be possible – Tima Nov 15 '10 at 16:05
2

I had the similar issue:

Activity A: singleInstance
Activity B: singleInstance
Activity C: singleInstance

A starts B 
B starts C
C wants to start A:

here if I use:

finish();
startActivity(A);

something wired happens: Activity B comes to foreground instead of A! but if I change the code like this:

startActivity(A);
finish();

everything seems ok and Activity A comes visible.

I don't know what's the problem, but it seems that in the first case, C is finished before executing the startActivity command so that the back stack handles the situation and shows its top activity which is B! but in the second case, everything happens normally.

herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
narges
  • 31
  • 4
  • When you finish() the application, android pulls the LRU activity from stack, which is B. Also, which makes me think that finish() is immediate and not asynchronous. – Mehmet AVŞAR Apr 08 '14 at 14:34
0

I usually do startActivity() before finish() as I think that'd make sure the new screen comes out before the previous goes out.

I have a login page in my app. After user login successfully, the login activity is gone and main activity is up. It works fine in the Android 4.

Today I wanted to rewrite it in Material design. However, I got a big problem. New Android studio creates blank activity with material design which I think takes many resources. The same process, but I got the error

11-26 18:20:44.450 18397-18397/? I/Choreographer: Skipped 42 frames!  The application may be doing too much work on its main thread.
11-26 18:20:44.485 18397-18408/? I/art: Background partial concurrent mark sweep GC freed 2864(191KB) AllocSpace objects, 4(43MB) LOS objects, 13% free, 100MB/116MB, paused 8.056ms total 39.767ms

It said my apps takes many resources when mainActivity starts in my phone logcat. I have nothing in mainActivity just that it is the default Material Design layout.

I reversed the order and now it works without error on my phone.

Dimitar
  • 4,402
  • 4
  • 31
  • 47
hatted
  • 1,535
  • 1
  • 15
  • 26