Hoàn thành hoạt động cũ và bắt đầu hoạt động mới hoặc ngược lại


80

Tôi biết, tôi nhận được cùng một kết quả với cả hai đoạn mã

finish();
startActivity(newActivity);

startActivity(newActivity);
finish();

Tôi muốn biết ý kiến ​​của bạn, nếu có sự khác biệt lớn giữa chúng. Cái này tốt hơn những cái khác phải không? Nếu vậy, tại sao?

Câu trả lời:


61

Khi bạn thực hiện startActivity (), tất cả những gì cần làm là đăng ý định của bạn trong một hàng đợi các sự kiện. Việc bắt đầu hoạt động thực tế diễn ra không đồng bộ trong tương lai gần. Vì vậy, tôi không thấy sự khác biệt lớn giữa hai.


1
nó có vẻ hợp lý với tôi là tốt
Tima

6
Hình ảnh động là khác nhau đối với tôi. Xem câu trả lời của tôi dưới đây.
Monstieur

nhưng cách tiếp cận hoàn toàn SAI .. Có các cờ (cho mục đích cũng như trong tệp kê khai) thực sự tồn tại cho các trường hợp sử dụng này.
Ewoks

@Ewoks hãy đi đầu, nghĩa là gì, cờ nào?
Anthony

3
Thực sự có một sự khác biệt lớn trong hành vi tác vụ ứng dụng. Tôi đã giải thích vấn đề trong một câu trả lời riêng.
Vit Khudenko

27

Hoạt ảnh rõ ràng là khác nhau (ít nhất là trên 4.1 trở đi). finish()Hoạt động gọi đầu tiên bắt đầu làm mờ dần hoạt động đầu tiên trước đó và bạn có thể nhanh chóng thấy nền đen trước khi hoạt động mới mờ dần. Cuộc gọi startActivity()đầu tiên sẽ mờ dần trong hoạt động mới trên hoạt động cũ và nền đen không hiển thị.


16

Có một sự khác biệt quan trọng trong hành vi tác vụ ứng dụng tùy thuộc vào thứ tự của startActivity()finish()lời gọi.

Trường hợp mà tôi đang mô tả chỉ nằm trong phạm vi tình huống khi hoạt động hiện tại (hoạt động đang bị dừng) là hoạt động duy nhất trong tác vụ.

Thông thường, bạn sẽ mong đợi rằng ý định bắt đầu (ý định bạn tạo để bắt đầu một hoạt động khác) không bị hệ thống thay đổi. Và đó không phải là trường hợp nếu finish()được gọi vào hoạt động cuối cùng trong tác vụ trước khi gọi startActivity().

Trong trường hợp này, ActivityManager, một thành phần hệ thống, trong khi thực thi cờ startActivity() sẽ thêm Intent.FLAG_ACTIVITY_NEW_TASK vào ý định của bạn.

Khi điều này xảy ra, người ta có thể nhận thấy một mục nhật ký trong LogCat tương tự như mục này:

W / ActivityManager: startActivity được gọi khi kết thúc ActivityRecord {4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 f}; buộc Intent.FLAG_ACTIVITY_NEW_TASK cho: Intent {cmp = com.foo.bar / com.foo.bar.MainActivity}

Và đây là bước ngoặt mà từ đó (trong một số điều kiện) mọi thứ có thể trở nên sai lầm.

Tóm lại, nếu bạn muốn ở một khía cạnh an toàn (thay vì gặp phải các tác dụng phụ không mong muốn của việc FLAG_ACTIVITY_NEW_TASKđược thêm vào mục đích), thì thứ tự phải là:

  • startActivity()
  • finish()

Demo dự án .

Ghi màn hình:


Nhìn vào mã nguồn, cuối cùng Activity.startActivity () gọi ActivityThread.sendActivityResult (), lần lượt gọi nó là ScheduleSendResult () mà chỉ thêm hoạt động vào một hàng đợi. Một chuỗi sẽ xử lý nó sau. Mặt khác, finish () gọi ActivityManagerNative.finishActivity () để kết thúc hoạt động ngay lập tức.
Emmanuel

@Emmanuel, tôi không biết liệu tuyên bố của bạn có liên quan đến vấn đề tôi đã mô tả hay không. :)
Vit Khudenko

9

Ngoài câu trả lời Emmanuels:

Cả hai phương thức startActivityfinishsẽ được lên lịch sau khi kết thúc phương thức gọi, vì cả hai đều được xử lý bởi luồng giao diện người dùng.


7

Tôi sẽ thực hiện lựa chọn thứ hai, tôi không ủng hộ điều này trên bất kỳ thứ gì mà tôi đã tra cứu từ các nguồn chính thức, nhưng, sẽ hợp lý hơn nếu khởi chạy hoạt động mới trước khi bạn gọi kết thúc, theo cách đó hoạt động mới xuất hiện thông qua một ý định , và hoạt động nền hiện có thể gọi tất cả các phương pháp dọn dẹp của nó.

Nếu bạn làm theo cách khác, có thể ý định sẽ không có thời gian để bắt đầu trước khi việc dọn dẹp hoàn tất. Tức là hoạt động sẽ gọi startActivity () sau khi gọi xong ()?

Tôi hy vọng bạn hiểu những gì tôi đang cố gắng trình bày, tôi sẽ làm tùy chọn thứ hai chỉ để được an toàn.


Vâng, tôi hiểu ý tưởng của bạn. Nghe có vẻ hợp lý. Nhưng tôi không thể tưởng tượng được mình, khi tình huống này có thể xảy ra
Tima

2

Tôi đã gặp vấn đề tương tự:

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

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

ở đây nếu tôi sử dụng:

finish();
startActivity(A);

điều gì đó có dây đã xảy ra: Hoạt động B xuất hiện ở nền trước thay vì A! nhưng nếu tôi thay đổi mã như thế này:

startActivity(A);
finish();

mọi thứ có vẻ ổn và Hoạt động A xuất hiện.

Tôi không biết vấn đề là gì, nhưng có vẻ như trong trường hợp đầu tiên, C đã hoàn thành trước khi thực hiện lệnh startActivity để ngăn xếp phía sau xử lý tình huống và hiển thị hoạt động hàng đầu của nó là B! nhưng trong trường hợp thứ hai, mọi thứ diễn ra bình thường.


Khi bạn hoàn thành () ứng dụng, android kéo hoạt động LRU từ ngăn xếp, đó là B. Ngoài ra, điều này khiến tôi nghĩ rằng finish () là ngay lập tức và không phải là không đồng bộ.
Mehmet AVŞAR

0

Tôi thường làm startActivity()trước đây finish()vì tôi nghĩ rằng sẽ đảm bảo màn hình mới xuất hiện trước khi màn hình trước đó tắt.

Tôi có một trang đăng nhập trong ứng dụng của mình. Sau khi người dùng đăng nhập thành công, hoạt động đăng nhập không còn nữa và hoạt động chính vẫn hoạt động. Nó hoạt động tốt trong Android 4.

Hôm nay tôi muốn viết lại nó trong Material design. Tuy nhiên, tôi có một vấn đề lớn. Studio Android mới tạo ra hoạt động trống với thiết kế material design mà tôi nghĩ là tốn nhiều tài nguyên. Quy trình tương tự, nhưng tôi gặp lỗi

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

Nó cho biết các ứng dụng của tôi chiếm nhiều tài nguyên khi mainActivitykhởi động trong logcat điện thoại của tôi. Tôi không có gì mainActivitychỉ vì nó là bố cục Material Design mặc định.

Tôi đã đảo ngược thứ tự và bây giờ nó hoạt động mà không có lỗi trên điện thoại của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.