8

Tôi đã sử dụng mẫu này một chút. Dưới đây là một ví dụ rất giả tạo của một chỉ AsyncTask + tiến bộ:AsyncTask, Fragments, Views và Backstacks

new AsyncTask<Void, Void, Void>() { 
    WeakReference<MyFragment> weakFragment = new WeakReference<MyFragment>(MyFragment.this); 

    @Override 
    protected void onPreExecute() { 
     Fragment fragment = weakFragment.get(); 
     if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.VISIBLE);   
    } 

    @Override 
    protected Document doInBackground(Void... params) { 
     Fragment fragment = weakFragment.get(); 
     if(fragment == null) return null; 

     // Do something ... 
    } 

    @Override 
    protected void onPostExecute() {     
     Fragment fragment = weakFragment.get(); 
     if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.GONE); 
    } 
}.execute(); 

Nó hoạt động ổn với những thay đổi hướng, nhưng tôi đã nhận thấy các mảnh vỡ là không null và fragment.getView() là null khi tôi bật mảnh vỡ phía sau. Điều đó rõ ràng gây ra sự cố này. Bạn đang sử dụng cách tiếp cận nào? Tôi dường như không thể tìm thấy một giải pháp hoàn hảo trực tuyến. Lưu ý quan trọng, đây là một mảnh và tôi gọi setRetainInstance(true); trên đoạn đó trong onActivityCreated (...) của nó.

+0

Sử dụng xe buýt nhắn tin hoặc bộ thu phát nội bộ. – 323go

+0

Đối với thanh tiến trình? : | Đó là một chút nhiều bạn không nghĩ? – JVillella

Trả lời

4

AsyncTask là một tác vụ không đồng bộ có nghĩa là bạn thường không biết khi nào công việc được hoàn thành và khi nó gọi onPostExecute(). Tôi nghĩ rằng vấn đề của bạn là ở đây. Khi bạn xoay thiết bị của mình, asynctask vẫn chưa hoàn thành và khung nhìn phân mảnh của bạn bị hủy và tái tạo lại rất nhanh trong khi asynctask vẫn còn trên luồng công nhân và khi nó thực hiện công việc, đoạn của bạn có một khung nhìn và giá trị trả về của getView không phải là null. Nhưng nếu thời gian quay mất nhiều, bạn sẽ nhận được nullAsyncTask đã hoàn tất nhưng đoạn của bạn không có bất kỳ chế độ xem nào. Bây giờ kịch bản này là chính xác xảy ra với backstack của bạn Khi bạn đẩy mảnh của bạn trên để backstack xem của nó bị phá hủy (look at the picture) nhưng bản thân mảnh không phải là (fragment trả về bố trí từ backstack). Bây giờ, hãy hoàn tất AsyncTask và gọi phương thức fragmentgetView của bạn và liều đó không có bất kỳ view để bạn sẽ nhận được NPE.

Giải pháp của tôi:

Trước tiên, bạn nên sử dụng WeakReference<ProgressBar> thay vì WeakReference<MyFragment> và trong onPostExecute() kiểm tra cho dù đó là null hay không, nếu nó là null không làm gì cả vì giá trị mặc định là vô hình nếu nó không phải là null gọi setVisibility(View.GONE).

Cập nhật:

đoạn là còn sống nhưng quan điểm đã được dealloc'd. Đây có phải là không?

Có, chỉ cần nhìn vào hình 2 từ liên kết. Khi đoạn đang hoạt động (hộp màu xanh lá cây) the fragment added to back stack mảnh đi đến , onStoponDestroyView. Sau đó, khi mảnh vỡ bật lên từ phía sau ngăn xếp nó đi ngay đến onCreateView liên kết mũi tên với văn bản này: the fragment returns to the layout from backstack.

Để xác nhận câu trả lời của tôi, bạn có thể tạo AsyncTask và gọi SystemClock.sleep(30000) bên trong số doInbackground của mình. Bây giờ bạn có thể đẩy mảnh của bạn vào backstack và bật lên từ backstack không có ngoại lệ bởi vì asynctask đã không hoàn thành và khi nó sẽ gọi onPostExecute() đoạn của bạn đã có một cái nhìn.

Một điều tốt bạn có thể thấy là setRetainInstance

này chỉ có thể được sử dụng với các mảnh vỡ không trong ngăn xếp trở lại.

Vì vậy, khi bạn đẩy mảnh của bạn vào ngăn xếp lại nó thể phá hủy hoàn toàn và bạn có thể được tham khảo đoạn mới khi nó bật lên. Nhưng khi bạn sử dụng setRetainInstance(true); để thay đổi cấu hình, đoạn của bạn được giữ lại trên Hoạt động tạo lại có nghĩa là cùng một đoạnonCreate không được gọi. Và đây là một điều rất quan trọng vì nếu bạn bắt đầu AsyncTask theo phương pháp onCreate, khi bạn đẩy đoạn của bạn vào ngăn xếp và bật lên, bạn có thể có đoạn mới và điều này có nghĩa là phương pháp onCreateAsyncTask khác Bị sa thải. Điều đó có nghĩa là bạn không có bất kỳ sự kiểm soát nào đối với số điện thoại gọi AsyncTask để xem ra cho rò rỉ bộ nhớ!

+0

Phải, tôi thấy bạn đến từ đâu. Đây là lý do tại sao tôi đang sử dụng tham chiếu yếu đến mảnh vỡ ở nơi đầu tiên. Các hành vi tôi nghĩ * Tôi đang chạy vào là mảnh vỡ còn sống nhưng quan điểm đã được dealloc'd. Điều này có thể không? Có lẽ một số làm rõ thêm về điều này sẽ giúp đỡ. – JVillella

+0

Cảm ơn sự giúp đỡ của bạn @mmlooloo. Điều này xóa mọi thứ, nhưng tôi vẫn không chắc chắn về cách thực hành tốt nhất trong việc xử lý fragment và fragment.getView() trong một tác vụ không đồng bộ. – JVillella

+0

Tôi không hiểu ý bạn là gì nhưng câu hỏi của bạn không phức tạp lắm, chỉ đơn giản là trong một số tình huống bạn có một mảnh và phân mảnh không có bất kỳ khung nhìn nào, vì vậy gọi getView sẽ dẫn đến NPE. – mmlooloo

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