Tác vụ và Ngăn xếp

Một ứng dụng thường chứa nhiều hoạt động. Mỗi hoạt động nên được thiết kế xung quanh một kiểu hành động cụ thể mà người dùng có thể thực hiện và bắt đầu các hoạt động khác. Ví dụ, một ứng dụng e-mail có thể có một hoạt động để hiển thị một danh sách các thư mới. Khi người dùng chọn một thư, một hoạt động mới sẽ mở ra để xem thư đó.

Hoạt động thậm chí có thể bắt đầu các hoạt động tồn tại trong các ứng dụng khác trên thiết bị. Ví dụ, nếu ứng dụng của bạn muốn gửi một thư e-mail, bạn có thể định nghĩa một ý định để thực hiện một hành động "gửi" và bao gồm một số dữ liệu, chẳng hạn như địa chỉ e-mail và nội dung. Một hoạt động từ một ứng dụng khác tự khai báo là có khả năng xử lý kiểu ý định này sẽ mở ra. Trong trường hợp này, ý định sẽ gửi một e-mail, sao cho hoạt động "soạn" của một ứng dụng e-mail sẽ bắt đầu (nếu nhiều hoạt động hỗ trợ cùng ý định, khi đó hệ thống cho phép người dùng chọn hoạt động sẽ sử dụng). Khi e-mail được gửi, hoạt động của bạn tiếp tục và dường như hoạt động e-mail là một phần ứng dụng của bạn. Mặc dù các hoạt động có thể đến từ những ứng dụng khác nhau, Android duy trì trải nghiệm người dùng mượt mà này bằng cách giữ cả hai hoạt động trong cùng tác vụ.

Tác vụ là một tập hợp gồm nhiều hoạt động mà người dùng tương tác với khi thực hiện một công việc nhất định. Các hoạt động được sắp xếp trong một chồng (ngăn xếp), theo thứ tự mở mỗi hoạt động.

Màn hình Trang chủ của thiết bị là nơi bắt đầu đối với hầu hết tác vụ. Khi người dùng chạm vào một biểu tượng trong trình khởi chạy ứng dụng (hoặc lối tắt trên màn hình Trang chủ), tác vụ của ứng dụng đó sẽ tiến ra tiền cảnh. Nếu không có tác vụ nào cho ứng dụng (ứng dụng chưa được sử dụng gần đây), khi đó một tác vụ mới sẽ được tạo và hoạt động "chính" cho ứng dụng đó sẽ mở ra thành hoạt động gốc trong chồng.

Khi hoạt động hiện tại bắt đầu một hoạt động khác, hoạt động mới sẽ bị đẩy lên trên cùng của chồng và có tiêu điểm. Hoạt động trước vẫn nằm trong chồng, nhưng bị dừng lại. Khi một hoạt động dừng, hệ thống giữ lại trạng thái hiện tại của giao diện người dùng của hoạt động đó. Khi người dùng nhấn nút Quay lại , hoạt động hiện tại được bật khỏi trên cùng của chồng (hoạt động bị hủy) và hoạt động trước tiếp tục (trạng thái trước đó của UI của nó được khôi phục). Các hoạt động trong chồng không bao giờ được sắp xếp lại, mà chỉ bị đẩy và bật khỏi chồng—bị đẩy lên trên chồng khi được bắt đầu bởi hoạt động hiện tại và bị bật khỏi chồng khi người dùng rời nó bằng cách sử dụng nút Quay lại. Như vậy, ngăn xếp vận hành như một cấu trúc đối tượng "vào cuối, ra đầu". Hình 1 minh họa hành vi này cùng một dòng thời gian thể hiện tiến độ giữa các hoạt động dọc theo ngăn xếp hiện tại ở từng thời điểm.

Hình 1. Biểu diễn cách mỗi hoạt động mới trong một tác vụ thêm một mục vào ngăn xếp. Khi người dùng nhấn nút Quay lại, hoạt động hiện tại bị hủy và hoạt động trước đó tiếp tục.

Nếu người dùng tiếp tục nhấn Quay lại, khi đó mỗi hoạt động trong chồng bị bật khỏi để hiện ra hoạt động trước, tới khi người dùng quay lại màn hình Trang chủ (hoặc trở về hoạt động đang chạy khi tác vụ bắt đầu). Khi tất cả hoạt động bị loại bỏ khỏi chồng, tác vụ sẽ không còn tồn tại.

Hình 2. Hai tác vụ: Tác vụ B nhận tương tác người dùng trong tiền cảnh, trong khi Tác vụ A nằm dưới nền, chờ được tiếp tục.

Hình 3. Một hoạt động đơn lẻ được khởi tạo nhiều lần.

Tác vụ là một đơn vị dính kết, có thể di chuyển tới "nền" khi người dùng bắt đầu một tác vụ mới hoặc đi đến màn hình Trang chủ, thông qua nút Home. Khi ở trong nền, tất cả hoạt động trong tác vụ bị dừng, nhưng ngăn xếp cho tác vụ vẫn không bị ảnh hưởng—tác vụ chỉ đơn thuần mất tiêu điểm trong khi một tác vụ khác thay thế, như minh họa trong hình 2. Khi đó, một tác vụ có thể quay lại "tiền cảnh" để người dùng có thể chọn ở nơi họ đã rời đi. Ví dụ, giả sử rằng tác vụ hiện tại (Tác vụ A) có ba hoạt động trong chồng của mình—hai trong số đó nằm dưới hoạt động hiện tại. Người dùng nhấn nút Trang chủ , sau đó bắt đầu một ứng dụng mới từ trình khởi chạy ứng dụng. Khi màn hình Trang chủ xuất hiện, Tác vụ A đi vào nền. Khi ứng dụng mới bắt đầu, hệ thống sẽ bắt đầu một tác vụ cho ứng dụng đó (Tác vụ B) bằng chồng các hoạt động của chính mình. Sau khi tương tác với ứng dụng đó, người dùng quay lại Trang chủ lần nữa và chọn ứng dụng đã bắt đầu Tác vụ A lúc đầu. Lúc này, Tác vụ A đi đến tiền cảnh—cả ba hoạt động trong chồng của nó đều giữ nguyên và hoạt động trên cùng của chồng được tiếp tục. Tại điểm này, người dùng cũng có thể chuyển trở lại Tác vụ B bằng cách đến Trang chủ và chọn biểu tượng ứng dụng đã bắt đầu tác vụ đó (hoặc bằng cách chọn tác vụ của ứng dụng từ màn hình tổng quan). Đây là một ví dụ về đa nhiệm trên Android.

Lưu ý: Nhiều tác vụ có thể được lưu giữ cùng lúc trong nền. Tuy nhiên, nếu người dùng đang chạy nhiều tác vụ nền tại cùng thời điểm, hệ thống có thể bắt đầu hủy các hoạt động nền để khôi phục bộ nhớ, khiến trạng thái của hoạt động bị mất. Xem phần sau đây về Trạng thái của hoạt động.

Vì các hoạt động trong ngăn xếp không bao giờ được sắp xếp lại, nếu ứng dụng của bạn cho phép người dùng bắt đầu một hoạt động cụ thể từ nhiều hơn một hoạt động, một thực thể mới của hoạt động đó sẽ được tạo và đẩy lên chồng (thay vì mang bất kỳ thực thể nào trước đó của hoạt động lên trên cùng). Như vậy, một hoạt động trong ứng dụng của bạn có thể được tạo phiên bản nhiều lần (thậm chí từ các tác vụ khác nhau), như minh họa trong hình 3. Như vậy, nếu người dùng điều hướng ngược lại bằng cách sử dụng nút Quay lại, mỗi thực thể của hoạt động được hiển thị theo thứ tự được mở (mỗi hoạt động có trạng thái UI của chính chúng). Tuy nhiên, bạn có thể sửa đổi hành vi này nếu không muốn một hoạt động được khởi tạo nhiều hơn một lần. Cách làm như vậy được bàn trong phần sau về Quản lý Tác vụ.

Để tóm tắt hành vi mặc định đối với các hoạt động và tác vụ:

  • Khi Hoạt động A bắt đầu Hoạt động B, Hoạt động A bị dừng, nhưng hệ thống giữ lại trạng thái của nó (chẳng hạn như vị trí cuộn và văn bản được nhập vào các mẫu). Nếu người dùng nhấn nút Quay lại khi đang trong Hoạt động B, Hoạt động A sẽ tiếp tục với trạng thái được khôi phục.
  • Khi người dùng rời khỏi một tác vụ bằng cách nhấn nút Trang chủ, hoạt động hiện tại bị dừng và tác vụ của nó sẽ đưa xuống dưới nền. Hệ thống sẽ giữ lại trạng thái của mọi hoạt động trong tác vụ. Nếu sau đó người dùng tiếp tục tác vụ bằng cách chọn biểu tượng trình khởi chạy đã bắt đầu tác vụ, tác vụ sẽ vào tiền cảnh và tiếp tục hoạt động ở trên cùng của chồng.
  • Nếu người dùng nhấn nút Quay lại, hoạt động hiện tại bị bật khỏi chồng và bị hủy. Hoạt động trước đó ở trong chồng sẽ được tiếp tục. Khi một hoạt động bị hủy, hệ thống không giữ lại trạng thái của hoạt động đó.
  • Hoạt động có thể được khởi tạo nhiều lần, thậm chí từ các tác vụ khác.

Thiết kế Điều hướng

Để biết thêm về cách điều hướng ứng dụng hoạt động trên Android, hãy đọc hướng dẫn Điều hướng của Thiết kế Android.

Lưu Trạng thái của Hoạt động

Như được đề cập ở trên, hành vi mặc định của hệ thống giữ nguyên trạng thái của một hoạt động khi nó bị dừng. Bằng cách này, khi người dùng điều hướng trở lại một hoạt động trước đó, giao diện người dùng của nó sẽ xuất hiện như lúc bị rời đi. Tuy nhiên, bạn có thể—và nên—chủ động giữ lại trạng thái của các hoạt động của mình bằng cách sử dụng các phương pháp gọi lại, trong trường hợp hoạt động bị hủy và phải được tạo lại.

Khi hệ thống dừng một trong các hoạt động của bạn (chẳng hạn như khi một hoạt động mới bắt đầu hoặc tác vụ di chuyển về nền), hệ thống có thể hoàn toàn hủy hoạt động đó nếu nó cần khôi phục bộ nhớ hệ thống. Khi điều này xảy ra, thông tin về trạng thái của hoạt động sẽ bị mất. Nếu điều này xảy ra, hệ thống vẫn biết rằng hoạt động có một vị trí trong ngăn xếp, nhưng khi hoạt động được đưa tới vị trí trên cùng của chồng, hệ thống phải tạo lại nó (thay vì tiếp tục). Để tránh làm mất công việc của người dùng, bạn nên chủ động giữ lại nó bằng cách triển khai phương pháp gọi lại onSaveInstanceState() trong hoạt động của mình.

Để biết thêm thông tin về cách lưu trạng thái hoạt động của mình, hãy xem tài liệu Hoạt động .

Quản lý Tác vụ

Cách Android quản lý tác vụ và ngăn xếp, như được mô tả bên trên—bằng cách đặt tất cả hoạt động được bắt đầu nối tiếp nhau vào cùng tác vụ và trong một chồng "vào cuối, ra đầu"—rất hiệu quả đối với hầu hết ứng dụng và bạn không phải lo lắng về cách thức các hoạt động của mình được liên kết với các tác vụ hay cách chúng tồn tại trong ngăn xếp. Tuy nhiên, bạn có thể quyết định rằng mình muốn gián đoạn hành vi thông thường. Có thể bạn muốn một hoạt động trong ứng dụng của mình bắt đầu một tác vụ mới khi nó được bắt đầu (thay vì được đặt trong tác vụ hiện tại); hoặc, khi bạn bắt đầu một hoạt động, bạn muốn mang lên trước một thực thể hiện tại của nó (thay vì tạo một thực thể mới trên cùng của ngăn xếp); hoặc, bạn muốn ngăn xếp của mình được xóa sạch tất cả các hoạt động, ngoại trừ hoạt động gốc khi người dùng rời khỏi tác vụ.

Bạn có thể làm những điều này và nhiều điều khác với các thuộc tính trong phần tử bản kê khai <activity> và cờ trong ý định mà bạn chuyển cho startActivity().

Về mặt này, các thuộc tính <activity> chính mà bạn có thể sử dụng là:

Và các cờ ý định chính mà bạn có thể sử dụng là:

Trong những phần sau, bạn sẽ thấy cách bạn có thể sử dụng những thuộc tính của bản kê khai và cờ ý định này để định nghĩa cách các hoạt động được liên kết với tác vụ và hành vi của chúng như thế nào trong ngăn xếp.

Bên cạnh đó, có phần bàn riêng về việc cân nhắc cách các tác vụ và hoạt động có thể được biểu diễn và quản lý trong màn hình tổng quan. Xem phần Màn hình Tổng quan để biết thêm thông tin. Thông thường, bạn nên cho phép hệ thống định nghĩa tác vụ và các hoạt động của bạn được biểu diễn như thế nào trong màn hình tổng quan, và bạn không cần sửa đổi hành vi này.

Chú ý: Hầu hết các ứng dụng không nên gián đoạn hành vi mặc định cho các hoạt động và tác vụ. Nếu bạn xác định rằng hoạt động của bạn cần phải sửa đổi hành vi mặc định, hãy thận trọng và đảm bảo kiểm tra khả năng sử dụng được của hoạt động đó trong khi khởi chạy và khi điều hướng trở lại nó từ các hoạt động và tác vụ khác bằng nút Quay lại. Đảm bảo kiểm tra hành vi điều hướng mà có thể xung đột với hành vi được kỳ vọng của người dùng.

Định nghĩa các chế độ khởi chạy

Các chế độ khởi chạy cho phép bạn định nghĩa một thực thể mới của một hoạt động được liên kết với tác vụ hiện tại như thế nào. Bạn có thể định nghĩa các chế độ khởi chạy khác nhau theo hai cách:

  • Sử dụng tệp bản kê khai

    Khi bạn khai báo một hoạt động trong tệp bản kê khai của mình, bạn có thể quy định hoạt động sẽ liên kết với các tác vụ như thế nào khi nó bắt đầu.

  • Sử dụng cờ Ý định

    Khi bạn gọi startActivity(), bạn có thể thêm một cờ vào Intent mà khai báo cách (hoặc liệu có hay không) hoạt động mới sẽ liên kết với tác vụ hiện tại.

Như vậy, nếu Hoạt động A bắt đầu Hoạt động B, Hoạt động B có thể định nghĩa trong bản kê khai của mình cách nó sẽ liên kết với tác vụ hiện tại (nếu có) và Hoạt động A cũng có thể yêu cầu cách mà Hoạt động B sẽ liên kết với tác vụ hiện tại. Nếu cả hai hoạt động đều định nghĩa cách Hoạt động B nên liên kết với một tác vụ thì yêu cầu của Hoạt động A (như định nghĩa trong ý định) được ưu tiên so với yêu cầu của Hoạt động B (như được định nghĩa trong bản kê khai của nó).

Lưu ý: Một số chế độ khởi chạy sẵn có cho tệp bản kê khai không sẵn có dưới dạng cờ cho một ý định và, tương tự, một số chế độ khởi chạy sẵn có dưới dạng cờ cho một ý định không thể được định nghĩa trong bản kê khai.

Sử dụng tệp bản kê khai

Khi khai báo một hoạt động trong tệp bản kê khai của bạn, bạn có thể quy định cách mà hoạt động sẽ liên kết với một tác vụ bằng cách sử dụng thuộc tính của phần tử <activity> , launchMode.

Thuộc tính launchMode quy định một chỉ lệnh về cách hoạt động sẽ được khởi chạy vào một tác vụ. Có bốn chế độ khởi chạy khác nhau mà bạn có thể gán cho thuộc tính launchMode :

"standard" (chế độ mặc định)
Mặc định. Hệ thống tạo một thực thể mới của hoạt động trong tác vụ là nơi mà nó được bắt đầu và định tuyến ý định tới đó. Hoạt động có thể được khởi tạo nhiều lần, mỗi thực thể có thể thuộc về các tác vụ khác nhau, và một tác vụ có thể có nhiều thực thể.
"singleTop"
Nếu một thực thể của hoạt động đã tồn tại ở trên cùng của tác vụ hiện tại, hệ thống sẽ định tuyến ý định tới thực thể đó thông qua một lệnh gọi tới phương pháp onNewIntent() của nó, thay vì tạo một thực thể mới của hoạt động. Hoạt động có thể được tạo phiên bản nhiều lần, mỗi thực thể có thể thuộc về các tác vụ khác nhau, và một tác vụ có thể có nhiều thực thể (nhưng chỉ nếu hoạt động nằm trên cùng của ngăn xếp không phải là một thực thể của hoạt động hiện có).

Ví dụ, giả sử ngăn xếp của một tác vụ bao gồm hoạt động gốc A với các hoạt động B, C, và D ở trên cùng (chồng là A-B-C-D; D ở trên cùng). Một ý định đến cho loại hoạt động D. Nếu D có chế độ khởi chạy "standard" mặc định, một thực thể mới của lớp sẽ được khởi chạy và chồng trở thành A-B-C-D-D. Tuy nhiên, nếu chế độ khởi chạy của D là "singleTop", thực thể hiện tại của D sẽ nhận ý định thông qua onNewIntent(), bởi nó nằm ở vị trí trên cùng của chồng—chồng vẫn là A-B-C-D. Tuy nhiên, nếu một ý định đến cho hoạt động loại B, khi đó một thực thể mới của B sẽ được thêm vào chồng ngay cả khi chế độ khởi chạy của nó là "singleTop".

Lưu ý: Khi một thực thể mới của hoạt động được tạo, người dùng có thể nhấn nút Quay lại để quay về hoạt động trước đó. Nhưng khi một thực thể hiện tại của hoạt động xử lý một ý định mới, người dùng không thể nhấn nút Quay lại để quay về trạng thái của hoạt động trước khi ý định mới đến trong onNewIntent().

"singleTask"
Hệ thống sẽ tạo ra một tác vụ mới và khởi tạo hoạt động ở gốc của tác vụ mới. Tuy nhiên, nếu một thực thể của hoạt động đã tồn tại trong một tác vụ riêng, hệ thống sẽ định tuyến ý định tới thực thể hiện tại thông qua một lệnh gọi tới phương pháp onNewIntent() của nó thay vì tạo một thực thể mới. Chỉ một thực thể của hoạt động có thể tồn tại ở một thời điểm.

Lưu ý: Mặc dù hoạt động bắt đầu một tác vụ mới, nút Quay lại sẽ vẫn đưa người dùng quay về hoạt động trước đó.

"singleInstance".
Giống như "singleTask", trừ khi hệ thống không khởi chạy bất kỳ hoạt động nào khác vào tác vụ đang nắm giữ thực thể. Hoạt động luôn là thành viên đơn lẻ và duy nhất của tác vụ; bất kỳ hoạt động nào được bắt đầu bởi hoạt động này sẽ mở ra trong một tác vụ riêng.

Lấy một ví dụ khác, ứng dụng Trình duyệt của Android khai báo rằng hoạt động trình duyệt web sẽ luôn mở tác vụ của chính mình—bằng cách quy định chế độ khởi chạy singleTask trong phần tử <activity>. Điều này có nghĩa rằng nếu ứng dụng của bạn phát hành một ý định để mở Trình duyệt Android, hoạt động của nó không được đặt trong cùng tác vụ như ứng dụng của bạn. Thay vào đó, hoặc là một tác vụ mới bắt đầu cho Trình duyệt hoặc, nếu Trình duyệt đã có một tác vụ đang chạy trong nền thì tác vụ đó sẽ được đưa lên trước để xử lý ý định mới.

Không phụ thuộc vào việc một hoạt động bắt đầu trong một tác vụ mới hay trong cùng tác vụ mà hoạt động đã bắt đầu, nút Quay lại sẽ luôn đưa người dùng về hoạt động trước đó. Tuy nhiên, nếu bạn bắt đầu một hoạt động mà quy định chế độ khởi chạy singleTask, khi đó nếu một thực thể của hoạt động đó tồn tại trong một tác vụ nền, toàn bộ tác vụ đó sẽ được đưa ra tiền cảnh. Tại thời điểm này , lúc này ngăn xếp bao gồm tất cả hoạt động từ tác vụ được mang ra, ở vị trí trên cùng của chồng. Hình 4 minh họa loại kịch bản này.

Hình 4. Biểu diễn cách thức một hoạt động với chế độ khởi chạy "singleTask" được thêm vào ngăn xếp. Nếu hoạt động đã là một phần của một tác vụ nền với ngăn xếp của chính nó, khi đó toàn bộ ngăn xếp cũng tiến về phía trước, ở trên cùng tác vụ hiện tại.

Để biết thêm thông tin về việc sử dụng các chế độ khởi chạy trong tệp bản kê khai, hãy xem tài liệu phần tử <activity> , trong đó có trình bày thêm về thuộc tính launchMode và các giá trị được chấp nhận.

Lưu ý: Hành vi mà bạn quy định cho hoạt động của mình bằng thuộc tính launchMode có thể bị khống chế bởi cờ có ý định bắt đầu hoạt động của bạn, như được trình bày trong phần tiếp theo.

Sử dụng cờ Ý định

Khi bắt đầu một hoạt động, bạn có thể sửa đổi liên kết mặc định giữa một hoạt động với tác vụ của nó bằng cách thêm cờ vào trong ý định mà bạn chuyển tới startActivity(). Những cờ mà bạn có thể sử dụng để sửa đổi hành vi mặc định là:

FLAG_ACTIVITY_NEW_TASK
Bắt đầu một hoạt động trong một tác vụ mới. Nếu đã có một tác vụ đang chạy cho hoạt động mà bạn đang bắt đầu, tác vụ đó sẽ được đưa ra tiền cảnh với trạng thái cuối cùng được khôi phục và hoạt động nhận ý định mới trong onNewIntent().

Điều này sẽ tạo ra cùng hành vi như giá trị "singleTask" launchMode, đã được trình bày ở phần trước.

FLAG_ACTIVITY_SINGLE_TOP
Nếu hoạt động đang được bắt đầu là hoạt động hiện tại (ở trên cùng của ngăn xếp), khi đó thực thể hiện có sẽ nhận một lệnh gọi đến onNewIntent(), thay vì tạo một thực thể của hoạt động mới.

Điều này sẽ tạo ra cùng hành vi như giá trị "singleTop" launchMode, đã được trình bày ở phần trước.

FLAG_ACTIVITY_CLEAR_TOP
Nếu hoạt động đang được bắt đầu đang chạy trong tác vụ hiện tại, khi đó thay vì khởi chạy một thực thể mới của hoạt động đó, tất cả các hoạt động khác bên trên nó đều bị hủy và ý định này được chuyển tới thực thể được tiếp tục của hoạt động (lúc này đang ở trên cùng), thông qua onNewIntent()).

Không có giá trị cho thuộc tính launchMode mà sinh ra hành vi này.

FLAG_ACTIVITY_CLEAR_TOP được sử dụng thường xuyên nhất cùng với FLAG_ACTIVITY_NEW_TASK. Khi được sử dụng cùng nhau, những cờ này là một cách để định vị hoạt động hiện tại trong một tác vụ khác và đặt nó vào vị trí nơi nó có thể hồi đáp ý định.

Lưu ý: Nếu chế độ khởi chạy của hoạt động được chỉ định là "standard", nó cũng bị loại bỏ khỏi chồng và một thực thể mới sẽ được khởi chạy thay chỗ nó để xử lý ý định đến. Đó là bởi một thực thể mới luôn được tạo cho ý định mới khi chế độ khởi chạy là "standard".

Xử lý quan hệ

Quan hệ sẽ cho biết một hoạt động ưu tiên thuộc về tác vụ nào hơn. Theo mặc định, tất cả các hoạt động từ cùng ứng dụng có quan hệ với nhau. Vì thế, theo mặc định, tất cả hoạt động trong cùng ứng dụng ưu tiên ở trong cùng tác vụ hơn. Tuy nhiên, bạn có thể sửa đổi quan hệ mặc định cho một hoạt động. Các hoạt động được định nghĩa trong các ứng dụng khác nhau có thể chia sẻ một quan hệ, hoặc các hoạt động được định nghĩa trong cùng ứng dụng có thể được gán các quan hệ tác vụ khác nhau.

Bạn có thể sửa đổi quan hệ cho bất kỳ hoạt động đã cho nào bằng thuộc tính taskAffinity của phần tử &lt;activity&gt; .

Thuộc tính taskAffinity lấy một giá trị xâu, đó phải là giá trị duy nhất từ tên gói mặc định được khai báo trong phần tử &lt;manifest&gt; , do hệ thống sử dụng tên đó để nhận biết quan hệ tác vụ mặc định cho ứng dụng.

Vấn đề quan hệ được xét trong hai trường hợp:

  • Khi ý định khởi chạy hoạt động chứa cờ FLAG_ACTIVITY_NEW_TASK .

    Theo mặc định, một hoạt động mới được khởi chạy vào tác vụ của hoạt động đã gọi startActivity(). Nó được đẩy lên cùng ngăn xếp như trình gọi. Tuy nhiên, nếu ý định được chuyển tới startActivity() chứa cờ FLAG_ACTIVITY_NEW_TASK , hệ thống sẽ tìm một tác vụ khác để chứa hoạt động mới. Thường thì đó là một tác vụ mới. Tuy nhiên, không nhất thiết phải như vậy. Nếu đã có một tác vụ hiện tại với cùng quan hệ như hoạt động mới, hoạt động sẽ được khởi chạy vào tác vụ đó. Nếu không, nó sẽ bắt đầu một tác vụ mới.

    Nếu cờ này khiến một hoạt động bắt đầu một tác vụ mới và người dùng nhấn nút Home để rời nó thì phải có một cách nào đó để người dùng điều hướng quay lại tác vụ. Một số đối tượng (chẳng hạn như trình quản lý thông báo) luôn bắt đầu các hoạt động trong một tác vụ bên ngoài, không bao giờ bắt đầu trong chính tác vụ của mình, vì thế chúng luôn đặt FLAG_ACTIVITY_NEW_TASK vào ý định mà chúng chuyển tới startActivity(). Nếu bạn có một hoạt động có thể được gọi ra bởi một đối tượng bên ngoài mà có thể sử dụng cờ này, hãy lưu ý là người dùng có một cách độc lập để quay lại tác vụ đã được bắt đầu, chẳng hạn như bằng một biểu tượng trình khởi chạy (hoạt động gốc của tác vụ có một bộ lọc ý định CATEGORY_LAUNCHER; xem phần Bắt đầu một tác vụ ở bên dưới).

  • Khi một hoạt động có thuộc tính allowTaskReparenting của nó được đặt thành "true".

    Trong trường hợp này, hoạt động có thể di chuyển từ tác vụ mà nó bắt đầu tới tác vụ mà nó có quan hệ khi tác vụ đó đi ra tiền cảnh.

    Ví dụ, giả sử rằng một hoạt động với chức năng báo cáo tình hình thời tiết ở các thành phố được chọn được định nghĩa là một phần trong một ứng dụng du lịch. Nó có cùng quan hệ như các hoạt động khác trong cùng ứng dụng (quan hệ ứng dụng mặc định) và nó cho phép tạo lại tập mẹ với thuộc tính này. Khi một trong các hoạt động của bạn bắt đầu hoạt động trình báo cáo thời tiết, ban đầu nó thuộc về cùng tác vụ như hoạt động của bạn. Tuy nhiên, khi tác vụ của ứng dụng du lịch đi ra tiền cảnh, hoạt động của trình báo cáo thời tiết được gán lại cho tác vụ đó và được hiển thị bên trong nó.

Mẹo: Nếu một tệp .apk chứa nhiều hơn một "ứng dụng" từ quan điểm của người dùng, bạn có thể muốn sử dụng thuộc tính taskAffinity để gán các quan hệ khác nhau cho hoạt động được liên kết với từng "ứng dụng".

Xóa ngăn xếp

Nếu người dùng rời một tác vụ trong khoảng thời gian dài, hệ thống sẽ xóa tác vụ của tất cả hoạt động ngoại trừ hoạt động gốc. Khi người dùng quay trở lại tác vụ, chỉ hoạt động gốc được khôi phục. Hệ thống sẽ hoạt động theo cách này, vì, sau một khoảng thời gian dài, người dùng có thể đã từ bỏ việc mà họ đang làm trước đó và quay lại tác vụ để bắt đầu một việc mới.

Có một số thuộc tính hoạt động mà bạn có thể sử dụng để sửa đổi hành vi này:

alwaysRetainTaskState
Nếu thuộc tính này được đặt thành "true" trong hoạt động gốc của một tác vụ, hành vi mặc định được mô tả sẽ không xảy ra. Tác vụ giữ lại tất cả hoạt động trong chồng của mình kể cả sau một khoảng thời gian dài.
clearTaskOnLaunch
Nếu thuộc tính này được đặt thành "true" trong hoạt động gốc của một tác vụ, chồng sẽ bị xóa tới hoạt động gốc bất cứ khi nào người dùng rời khỏi tác vụ và quay lại. Nói cách khác, nó ngược với alwaysRetainTaskState. Người dùng luôn quay lại tác vụ ở trạng thái ban đầu của nó, ngay cả sau khi rời khỏi tác vụ trong chỉ một lúc.
finishOnTaskLaunch
Thuộc tính này giống như clearTaskOnLaunch, nhưng nó hoạt động trên một tác vụ đơn lẻ chứ không phải một tác vụ toàn bộ. Nó cũng có thể khiến bất kỳ hoạt động nào thoát mất, bao gồm cả hoạt động gốc. Khi nó được đặt thành "true", hoạt động vẫn là một bộ phận của tác vụ chỉ cho phiên làm việc hiện tại. Nếu người dùng rời đi rồi quay lại tác vụ, nó không còn xuất hiện nữa.

Bắt đầu một tác vụ

Bạn có thể thiết lập một hoạt động làm điểm bắt đầu cho một tác vụ bằng cách đưa cho nó một bộ lọc ý định với "android.intent.action.MAIN" là hành động được quy định và "android.intent.category.LAUNCHER" là thể loại được quy định. Ví dụ:

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>

Một bộ lọc ý định loại này khiến một biểu tượng và nhãn cho hoạt động được hiển thị trong trình khởi chạy ứng dụng, cho phép người dùng khởi chạy hoạt động và quay lại tác vụ mà nó tạo ra vào bất cứ lúc nào sau khi nó được khởi chạy.

Khả năng thứ hai này là quan trọng: Người dùng chắc chắn có thể rời một tác vụ rồi quay lại sau bằng cách sử dụng trình khởi chạy hoạt động này. Vì lý do này, hai chế độ khởi chạy mà đánh dấu các hoạt động là luôn khởi tạo một tác vụ, "singleTask""singleInstance", sẽ chỉ được sử dụng khi hoạt động có một ACTION_MAIN và một bộ lọc CATEGORY_LAUNCHER. Ví dụ, hãy tưởng tượng chuyện gì sẽ xảy ra nếu thiếu bộ lọc: Một ý định khởi chạy một hoạt động "singleTask", khởi đầu một tác vụ mới và người dùng dành một khoảng thời gian làm việc trong tác vụ đó. Khi đó, người dùng nhấn nút Home . Lúc này, tác vụ được gửi tới nền và không hiển thị. Bây giờ, người dùng không có cách nào để quay lại tác vụ bởi nó không được biểu diễn trong trình khởi chạy ứng dụng.

Đối với những trường hợp mà bạn không muốn người dùng có thể quay lại một hoạt động, hãy đặt giá trị của phần tử <activity> , finishOnTaskLaunch thành "true" (xem Xóa chồng).

Bạn có thể tham khảo thêm thông tin về cách các tác vụ và hoạt động được trình bày và quản lý trong màn hình tổng quan sẵn có tại phần Màn hình Tổng quan.