2016-07-25 22 views
32

Phương thức commitNow() mới được thêm vào Android N và thư viện hỗ trợ phiên bản 24 có tài liệu giới hạn và hơi khó hiểu.FragmentTransaction commitNow() hoạt động trong nội bộ như thế nào?

Cam kết giao dịch này một cách đồng bộ. Bất kỳ phần bổ sung nào sẽ được khởi tạo và được đưa hoàn toàn về trạng thái vòng đời của máy chủ và mọi đoạn bị xóa sẽ bị rách theo đó trước khi trả về cuộc gọi này. Thực hiện giao dịch theo cách này cho phép các phần được thêm vào như là các thành phần được đóng gói, chuyên dụng theo dõi trạng thái vòng đời của máy chủ của chúng trong khi cung cấp bảo đảm an toàn hơn khi các đoạn đó được khởi tạo hoàn toàn và sẵn sàng. Các phân đoạn quản lý chế độ xem sẽ có các chế độ xem được tạo ra và được đính kèm.

Calling commitNow là thích hợp hơn để kêu gọi cam kết() tiếp theo FragmentManager.executePendingTransactions() như sau sẽ có tác dụng phụ của cố gắng để thực hiện tất cả các hiện giao dịch cấp phát cho dù đó là hành vi mong muốn hay không.

Giao dịch được thực hiện theo cách này có thể không được thêm vào ngăn xếp trở lại của FragmentManager, khi thực hiện như vậy sẽ phá vỡ các yêu cầu bảo đảm khác đối với các giao dịch không đồng bộ khác. Phương pháp này sẽ ném IllegalStateException nếu giao dịch trước đó được yêu cầu được thêm vào ngăn xếp lại với addToBackStack (Chuỗi).

Giao dịch chỉ có thể được cam kết với phương thức này trước khi hoạt động có chứa hoạt động lưu trạng thái của giao dịch đó. Nếu cam kết được cố gắng sau thời điểm đó, một ngoại lệ sẽ được ném. Điều này là do tiểu bang sau khi cam kết có thể bị mất nếu hoạt động cần được khôi phục từ trạng thái của nó. Xem commitAllowingStateLoss() cho tình huống có thể mất cam kết.

Tôi đã đánh dấu đậm phần mà tôi nghĩ rằng điều đó gây nhầm lẫn.

Vì vậy, mối quan tâm/câu hỏi chính của tôi là:

1 - KHÔNG ĐƯỢC thêm? Nó nói rằng tôi sẽ nhận được một IllegalStateException, do đó, nó sẽ được hoặc sẽ không được thêm vào?

2 - Tôi chấp nhận thực tế là tôi không thể sử dụng điều này nếu chúng tôi muốn thêm một đoạn trong hậu trường. Những gì nó không nói là bạn nhận được ngoại lệ này:

java.lang.IllegalStateException: This transaction is already being added to the back stack 

!!!! ????

Vì vậy, tôi không thể gọi số addToBackStack(String) vì nó gọi nội bộ cho tôi? Tôi xin lỗi nhưng ... cái gì? tại sao? nếu tôi không muốn nó được thêm vào trong backstack thì sao? Và nếu tôi cố gắng sử dụng mảnh vỡ đó từ hậu trường sau này nhưng vì nó KHÔNG THỂ được thêm vào, sau đó nó không có ở đó?

Có vẻ như đây là điều được mong đợi nếu tôi đang sử dụng commitAllowingStateLoss(), nhưng tôi thấy rằng commitNowAllowingStateLoss() cũng tồn tại, vì vậy ... loại logic nào?

TL; DR

Làm cách nào để commitNow() hoạt động trong nội bộ liên quan đến hậu trường?

+0

Và bây giờ 5 tháng sau, vẫn không ai biết! – EpicPandaForce

+0

@EpicPandaForce Đã trả lời! Hy vọng câu trả lời của tôi có thể làm hài lòng bạn :) –

+0

@NikoAdrianusYuwono Tôi sẽ có tiền thưởng lâu hơn một chút để đảm bảo, nhưng nó chắc chắn là một sự khởi đầu: p – EpicPandaForce

Trả lời

38

Thật là một điều tốt khi mã nguồn Android là nguồn mở khi chúng ta đối mặt với một số câu hỏi như thế này!

trả lời

Vì vậy, chúng ta hãy nhìn vào nguồn BackStackRecord here

@Override 
public void commitNow() { 
    disallowAddToBackStack(); 
    mManager.execSingleAction(this, false); 
} 

@Override 
public FragmentTransaction disallowAddToBackStack() { 
    if (mAddToBackStack) { 
     throw new IllegalStateException(
       "This transaction is already being added to the back stack"); 
    } 
    mAllowAddToBackStack = false; 
    return this; 
} 

mAddToBackStack sẽ được thiết lập là true nếu bạn gọi addToBackStack trong giao dịch của bạn.

Vì vậy, để trả lời câu hỏi của bạn, không addToBackStack không được gọi nội bộ khi bạn gọi commitNow(), Đó là thông báo ngoại lệ không rõ ràng. Tôi nghĩ rằng nó nên nói You're not allowed to add to backstack when using commitNow() thay vì thông báo hiện tại.

Bonus:

Nếu chúng ta đào sâu hơn vào mã nguồn FragmentManager here, commitNow() thực sự làm gần điều tương tự như executePendingTransactions() như viết ở trên, nhưng thay vì thực hiện tất cả các giao dịch cam kết trước đây, commitNow() sẽ chỉ cam kết giao dịch .

Tôi nghĩ đó là lý do chính tại sao commitNow() không cho phép bổ sung vào backstack vì nó không thể đảm bảo không có bất kỳ giao dịch đang chờ xử lý nào khác. Nếu commitNow() có thể thêm vào backstack, có khả năng chúng ta có thể phá vỡ chuỗi backstack của chúng ta sẽ dẫn đến điều bất ngờ.

+0

Vì vậy, dường như các tin nhắn IllegalStateException chỉ là không chính xác ... Cảm ơn Niko! – Kaizie

+0

@Kaizie Bạn được chào đón! Xin vui lòng chấp nhận câu trả lời nếu bạn nghĩ rằng đó là một trong những chính xác :) –

+1

Vâng, kiểm tra mã nguồn có vẻ như nó là câu trả lời đúng. Nhưng bằng cách nào đó tôi cảm thấy như họ đã bán API mới này trong google IO ... bởi vì họ đã cố gắng bán nó như là giải pháp tuyệt vời cho các vấn đề IllegalStateException phân đoạn sau khi tạm dừng hoạt động, nhưng bằng cách nào đó điều này không cung cấp đầy đủ các tính năng() bạn không thể thêm nó vào backstack ... vì vậy nó chỉ có thể được sử dụng trong các tình huống nhất định nếu ứng dụng của bạn cho phép thêm đoạn này mà không cần thêm nó vào backstack ... Dù sao, câu trả lời đúng! Cảm ơn! – Kaizie

Các vấn đề liên quan