12/08/2018, 11:00

Gọi onActivityResult trong Nested Fragment

Update latest 11/04/2016 Hiện tại Google đã update thư viện support v4, cho phép nested fragment có thể nhận trực tiếp callback từ onRequestPermissionResult() và onActivityResult, vì thế bài viết dưới đây không còn ý nghĩa nữa, nhưng có thể nó cũng giúp bạn hiểu 1 phần cơ chế Thông tin chi tiết các ...

Update latest 11/04/2016 Hiện tại Google đã update thư viện support v4, cho phép nested fragment có thể nhận trực tiếp callback từ onRequestPermissionResult() và onActivityResult, vì thế bài viết dưới đây không còn ý nghĩa nữa, nhưng có thể nó cũng giúp bạn hiểu 1 phần cơ chế Thông tin chi tiết các bạn có thể tham khảo dưới đây If you’re using Support v4 Fragments, nested fragments will now receive callbacks to onRequestPermissionsResult() (in addition to callbacks to onActivityResult(), fixed in 23.2.1).

----Deprecated-------- Đối với các lập trình viên Android, thì phương thức onActivityResult có lẽ đã quá quen thuộc. Từ activity A muốn triệu gọi một activity B để làm một việc x nào đó, sau khi thực hiện xong thì trả kết quả về cho A. Tại A, kết quả trả về từ B sẽ được xử lý trong hàm onActivityResult, rất đơn giản phải không. Vâng, quả thực rất đơn giản nếu như chúng ta gọi hàm startActivityForResult từ activity A.

Bài viết này tôi muốn chia sẻ với các bạn vấn đề tôi gặp phải trong quá trình làm thực tế, mà nó đã làm tôi mất rất nhiều công để fix, hi vọng các bạn sẽ giải quyết nó êm xuôi khi gặp phải tình huống này.

Tình huống tôi gặp phải như sau:

  • Có 1 activity, đặt tên là ActivityMain
  • Activity chứa 1 fragment đặt tên là FragmentLevelOne
  • FragmentLevelOne lại chứa trong nó 1 (hoặc n) fragment khác, đặt tên là FragmentLevelTwo. Trong FragmentLevelTwo có thể chứa fragment con và cứ như thế. Với dân android thì gọi đó là fragment lồng fragment hay chính xác hơn là Nested Fragment
  • Trong các nested fragment này, tôi gọi lệnh startActivityForResult để triệu gọi activity khác để thực hiện công việc nào đó, tạm gọi là ActivityWorker.

Đọc đến đây, chắc có lẽ các bạn sẽ nghĩ ngay rằng: “xời, thì sau khi ActivityWorker nó thực hiện xong nó sẽ trả về kết quả cho ActivityMain thôi, trong FragmentLevelTwo cài đè phương thức onActivityResult là sẽ xử lý được kết quả thôi mà”.

Vâng, đây chính là mấu chốt vấn đề. Quả thực, ở FragmentLevelTwo tôi đã thử sử dụng cả 2 kiểu gọi ActivityWorker: gọi trực tiếp bằng phương thức startActivityForResult và getActivity().startActivityForResult. Tuy nhiên, kết quả trả về từ ActivityWorker nó không trả về cho onActivityResult ở FragmentLevelTwo. Có lẽ các bạn sẽ cho điều này là hoang đường, không thể như thế được. Nhưng tình huống tôi gặp thì đúng là như vậy. Các bạn có biết tại sao không? Sau rất nhiều câu trả lời trên mạng, cuối cùng tôi đã tìm được câu trả lời và fix được vấn đề này.

Lý do tại sao? Đó là bởi vì fragment được thiết kế không dành cho mục đích lồng (nested). Do đó, một khi chúng ta mở rộng khả năng của nó, kiến trúc sử dụng fragment không thể kiểm soát được tất cả các tình huống, và dĩ nhiên, chúng ta phải tự kiểm soát. Tôi đã tìm ra được giải pháp ở trên mạng có thể giải quyết vấn đề này.

Trước hết, chúng ta tìm hiểu về việc gọi phương thức startActivityForResult và tại sao lại không có kết quả trả về onActivityResult trong nested fragment. Mặc dù chúng ta gọi phương thức startActivityForResult trực tiếp từ fragment nhưng thực tế, mọi thứ được kiểm soát bởi Activity. Mỗi khi chúng ta gọi phương thức startActivityForResult từ một fragment, requestCode sẽ bị thay đổi theo hướng gắn định danh của fragment vào code. Đây chính là mấu chốt của vấn đề. Việc thay đổi requestCode giúp cho Activity có thể đánh dấu xem fragment nào đã gửi request này mỗi khi nhận được kết quả trả về. Mỗi khi Activity nhận kết quả trả về, kết quả sẽ được gửi đến phương thức onActivityResult với requestCode đã chỉnh sửa và requestCode này sẽ được giải mã thành requestCode ban đầu và định danh của fragment. Sau đó, Activity sẽ gửi kết quả này đến fragment thông qua phương thức onActivityResult. Xong.

Vấn đề ở đây là: activity chỉ có thể gửi kết quả đến fragment nào đã attach trực tiếp vào activity mà thôi, còn với nested fragment thì không. Đó là lý do tại sao mà phương thức onActivityResult của nested fragment không bao giờ được gọi.

Giải pháp là gì?

Tìm kiếm trên mạng sẽ có rất nhiều giải pháp, các đại cao thủ trên stackoverflow sẽ cung cấp muôn vàn giải pháp. Tuy nhiên, tôi không tìm được giải pháp nào giải quyết triệt để vấn đề này. May thay, cuối cùng tôi đã thấy (Ơ rê ka)             </div>
            
            <div class=

0