2017-09-13 14 views
16

Tôi có mã Android/java cũ, chứa hai nguồn gốc từ IntentService, và các dịch vụ này không phải chạy trong các quy trình riêng biệt.LiveData vs Handler và LocalBroadcast

Câu hỏi đặt ra là cách trả lại kết quả từ các số IntentService này.

Một kết quả lợi nhuận dịch vụ bằng cách sử dụng Handler + Runnable, để chạy mã trong vòng lặp chính:

new Handler(Looper.getMainLooper()).post(new Runnable() { 
    @Override 
    public void run() { 
     MyApplication.get().setFoo(someThing); 
    } 
}); 

một trong những khác là sử dụng LocalBroadcastManager.getInstance(this).sendBroadcast(in); để gửi thông điệp tới Activity, và Activity đăng ký qua BroadcastReceiver trên tin nhắn trong onResume, và hủy đăng ký trong .

Tôi có đúng không và trong cả hai trường hợp, bạn có thể sử dụng LiveData để đơn giản hóa mọi thứ?

IntentService nên tạo LiveData và những người muốn kết quả nên observe nó, và khi dữ liệu mới đến IntentService nên gọi postValue, hoặc có thể có một số rạn để ngăn chặn việc sử dụng của LiveData đây?

+0

bạn đã kiểm tra điều này: https://stackoverflow.com/questions/44204978/how-to-update-livedata-of-a-viewmodel-from-background-service-and-update-ui –

+0

có bạn có thể thực hiện việc này –

+0

Sử dụng Trình nhận kết quả cho hoạt động liên lạc IntentService, bạn có thể trao đổi dữ liệu giữa các thành phần này. Nó rất hữu ích cho giải pháp thay thế. –

Trả lời

3

Tôi nghĩ rằng LiveData sẽ không giúp bạn gửi bất kỳ dữ liệu nào từ Service đến các thành phần khác.

Vấn đề với giao tiếp từ bất kỳ Service đến các thành phần khác là bạn thường không có được tham chiếu trực tiếp đến Service, do đó bạn không thể trực tiếp "đăng ký" với thông báo.

Về mặt lý thuyết, nếu Service chạy trong cùng một quy trình, bạn có thể liên kết nó, lấy tham chiếu đến đối tượng Service và sau đó trực tiếp thực hiện đăng ký. Tuy nhiên, đây thường là quá mức cần thiết và tôi không thấy mẫu này được sử dụng rộng rãi.

Trong ví dụ của bạn, có hai cơ chế giao tiếp:

  1. Dịch vụ đạt tĩnh để đối tượng Application và đặt ra một số dữ liệu. Đây là một giao tiếp thông qua nhà nước toàn cầu, và thường được coi là một mô hình chống.
  2. Truyền thông qua LocalBroadcastManager

Từ hai cơ chế trên, tôi sẽ chỉ sử dụng # 2 và tránh # 1 bằng mọi giá.

Quay lại LiveData.

Để có thể nhận được đối tượng LiveData từ Service, bạn sẽ cần phải có tham chiếu đến số Service đó. Điều này thường không thể trừ khi bạn ràng buộc Service trong cùng một quá trình hoặc sử dụng một số hack xấu xí liên quan đến trạng thái toàn cầu.

Do đó, tính hữu dụng của LiveData trong ngữ cảnh này rất hạn chế.

Nhân tiện, trong khi LocalBroadcastManager không sao, tôi thấy cơ chế này quá phức tạp và hạn chế. Do đó, nếu Service chạy trong cùng một quá trình, tôi thích sử dụng EventBus để liên lạc từ Service đến các thành phần khác (hoặc ngược lại).

Ví dụ về thông báo như vậy bạn có thể thấy trong số SQLite benchmarking application mà tôi đã viết cách đây vài ngày. Trong ứng dụng này, TestService đăng thay đổi trạng thái và kết quả kiểm tra lên EventBus dưới dạng sự kiện dính và TestActivity đăng ký các sự kiện đó.

1

Cả hai phương pháp đều làm việc với việc sử dụng LiveData vì mục đích của LiveData là có nó trên một chuỗi khác và vẫn thông báo cho người dùng khi có điều gì đó thay đổi. Có vẻ như nó chắc chắn sẽ thay thế LocalBroadcastManager.getInstance(this).sendBroadcast(in); và IntentService của bạn sẽ postValue. Chỉ cần có hoạt động của bạn hoặc bất cứ điều gì cần phải nhận thức được những thay đổi trở thành một người quan sát.

+0

"Chỉ cần có hoạt động của bạn hoặc bất cứ điều gì mà cần phải nhận thức được những thay đổi trở thành một người quan sát" - làm thế nào chính xác điều này nên được thực hiện? – Vasiliy