Khi nào nên sử dụng RxJava trong Android và khi nào nên sử dụng LiveData từ Thành phần kiến ​​trúc Android?


186

Tôi không hiểu lý do sử dụng RxJava trong Android và LiveData từ Cấu trúc kiến ​​trúc Android. Nó sẽ thực sự hữu ích nếu các cách sử dụng và sự khác biệt giữa cả hai được giải thích cùng với ví dụ mẫu dưới dạng mã giải thích sự khác biệt giữa cả hai.


6
Bạn đã tìm thấy một lý do tốt chưa? Tôi cũng đang tự hỏi như vậy ...
IgorGanapolsky

Câu trả lời:


117

Android LiveData là một biến thể của mẫu quan sát ban đầu, với việc bổ sung các chuyển đổi hoạt động / không hoạt động. Như vậy, nó rất hạn chế trong phạm vi của nó.

Sử dụng ví dụ được mô tả trong Android LiveData , một lớp được tạo để giám sát dữ liệu vị trí và đăng ký và hủy đăng ký dựa trên trạng thái ứng dụng.

RxJava cung cấp các toán tử được khái quát hơn nhiều. Giả sử rằng điều này có thể quan sát được sẽ cung cấp dữ liệu vị trí:

Observable<LocationData> locationObservable;

Việc triển khai có thể quan sát có thể được xây dựng bằng cách sử dụng Observable.create()để ánh xạ các hoạt động gọi lại. Khi có thể quan sát được đăng ký, cuộc gọi lại được đăng ký và khi nó bị hủy đăng ký, cuộc gọi lại không được đăng ký. Việc thực hiện trông rất giống với mã được cung cấp trong ví dụ.

Chúng ta cũng giả sử rằng bạn có thể quan sát được phát ra đúng khi ứng dụng đang hoạt động:

Observable<Boolean> isActive;

Sau đó, bạn có thể cung cấp tất cả các chức năng của LiveData bằng cách sau đây

Observable<LocationData> liveLocation =
  isActive
    .switchMap( active -> active ? locationObservable : Observable.never() );

Nhà switchMap()điều hành sẽ cung cấp vị trí hiện tại dưới dạng luồng hoặc không có gì nếu ứng dụng không hoạt động. Một khi bạn có liveLocationthể quan sát được, có rất nhiều điều bạn có thể làm với nó bằng các toán tử RxJava. Ví dụ yêu thích của tôi là:

liveLocation.distinctUntilChanged()
  .filter( location -> isLocationInAreaOfInterest( location ) )
  .subscribe( location -> doSomethingWithNewLocation( location ) );

Điều đó sẽ chỉ thực hiện hành động khi vị trí thay đổi, và vị trí thú vị. Bạn có thể tạo các hoạt động tương tự kết hợp các toán tử thời gian để xác định tốc độ. Quan trọng hơn, bạn có thể cung cấp kiểm soát chi tiết xem liệu các hoạt động xảy ra trong luồng chính hay luồng nền hay nhiều luồng, sử dụng toán tử RxJava.

Quan điểm của RxJava là nó kết hợp điều khiển và thời gian vào một vũ trụ duy nhất, sử dụng các hoạt động được cung cấp từ thư viện hoặc thậm chí các hoạt động tùy chỉnh mà bạn cung cấp.

LiveData chỉ giải quyết một phần nhỏ của vũ trụ đó, tương đương với việc xây dựng liveLocation.


2
Cảm ơn, các tài liệu LiveData dường như không tham chiếu mẫu vị trí nữa. Có nhiều điểm thú vị hơn (với một mẫu vị trí) ở đây: androidkt.com/livingata
Daniel Wilson

5
@DanielWilson liên kết không có sẵn nữa.
Tura

Anh bạn tôi không thể nhớ wtf đã ở trên liên kết đó: DI như mã mẫu của Mark Allison cho một dữ liệu trực tiếp: blog.stommeandroid.com/arch architecture
Daniel Wilson

3
The point of RxJava is that it combines control and timing into a single universe, using operations provided from the library, or even custom operations that you provide. Nhưng không phải là vòng đời LiveData nhận thức được. Nếu chúng ta sử dụng Rx, chúng ta sẽ không phải xử lý các thay đổi trong vòng đời chứ?
Sparker0i

@ Sparker0i có điểm ở đây. RxJava không nhận thức được vòng đời. chúng ta phải xử lý bằng tay. như trong LiveData, nó đã được chăm sóc vòng đời.
Aks4125

119

Về câu hỏi ban đầu, cả RxJava và LiveData đều bổ sung cho nhau thực sự tốt.

LiveDatatỏa sáng trên lớp ViewModel, với sự tích hợp chặt chẽ với vòng đời của Android và ViewModel. RxJavacung cấp nhiều khả năng hơn trong các phép biến đổi (như được đề cập bởi @Bob Dalgleish).

Hiện tại, chúng tôi đang sử dụng RxJavatrong các lớp nguồn dữ liệu và kho lưu trữ và được chuyển thành LiveData(sử dụng LiveDataReactiveStreams) trong ViewModels (trước khi hiển thị dữ liệu cho các hoạt động / đoạn) - khá hài lòng với phương pháp này.


8
Nếu chúng tôi hiểu bạn một cách chính xác, thì LiveData chỉ hữu ích cho các triển khai dành riêng cho giao diện người dùng Android. Nếu chúng ta chỉ xây dựng một ứng dụng chung với Kiến trúc sạch và chia sẻ kiến ​​trúc này với các nền tảng khác, thì RxJava có phù hợp hơn LiveData không?
IgorGanapolsky

@IgorGanapolsky bạn sử dụng ngôn ngữ / khung nào cho ứng dụng chung?
kzotin

API độc lập với Android và Clean Arch được viết bằng Java / Kotlin.
IgorGanapolsky

1
bạn có thể đề xuất bất kỳ ví dụ hoạt động nào của LiveDataReactiveStreams trong câu trả lời của bạn không?
Pawan

2
@kzotin bạn không cần điều đó observeOn, LiveDataReactiveStreamsdù sao đi nữa bằng cách gọi LiveData.postValue(). Và không có gì đảm bảo rằng ý chí của bạn subscribeOnsẽ có bất kỳ ảnh hưởng nào nói chung.
arekolek

77

Có nhiều sự khác biệt giữa LiveData và RxJava:

  1. LiveData không phải là STREAM trong khi ở RxJava, mọi thứ (nghĩa đen là mọi thứ) đều là STREAM .
  2. LiveData là một lớp giữ dữ liệu quan sát được. Không giống như một thứ có thể quan sát thông thường, LiveData nhận biết vòng đời, có nghĩa là nó tôn trọng vòng đời của các thành phần ứng dụng khác, chẳng hạn như các hoạt động, đoạn hoặc dịch vụ. Nhận thức này đảm bảo LiveData chỉ cập nhật các nhà quan sát thành phần ứng dụng đang ở trạng thái vòng đời hoạt động.
  3. LiveData là đồng bộ , vì vậy bạn không thể thực thi một đoạn mã (cuộc gọi mạng, thao tác cơ sở dữ liệu, v.v.) không đồng bộ chỉ sử dụng LiveData như bạn làm với RxJava.
  4. Điều tốt nhất bạn có thể làm để khai thác phần lớn bộ đôi này là sử dụng RxJava cho logic nghiệp vụ của bạn (cuộc gọi mạng, thao tác dữ liệu, v.v., bất cứ điều gì xảy ra trong và ngoài Kho lưu trữ ) và sử dụng LiveData cho lớp trình bày của bạn. Bằng cách này, bạn có được khả năng chuyển đổi và truyền phát cho logic nghiệp vụ và hoạt động nhận biết vòng đời cho giao diện người dùng của bạn.
  5. LiveData và RxJava khen nhau nếu được sử dụng cùng nhau. Ý tôi là, hãy làm mọi thứ với RxJava và cuối cùng khi bạn muốn cập nhật UI, hãy làm một cái gì đó giống như mã được đưa ra dưới đây để thay đổi Quan sát của bạn thành LiveData. Vì vậy, Chế độ xem (UI) của bạn quan sát LiveData trong ViewModel trong đó LiveData của bạn không là gì ngoài MutableLiveData không thể thay đổi (hoặc MutableLiveData là LiveData có thể thay đổi).
  6. Vì vậy, câu hỏi ở đây là, tại sao bạn thậm chí nên sử dụng LiveData ở nơi đầu tiên? Như bạn có thể thấy bên dưới trong mã, bạn lưu trữ phản hồi của bạn từ RxJava đến MutableLiveData (hoặc LiveData) và LiveData của bạn là nhận biết vòng đời, do đó, theo cách nào đó, dữ liệu của bạn là nhận biết vòng đời. Bây giờ, chỉ cần tưởng tượng khả năng khi dữ liệu của bạn biết khi nào và khi nào không cập nhật giao diện người dùng.
  7. LiveData không có lịch sử (chỉ trạng thái hiện tại). Do đó, bạn không nên sử dụng LiveData cho ứng dụng trò chuyện.
  8. Khi bạn sử dụng LiveData với RxJava, bạn không cần những thứ như MediatorLiveData , SwitchMap , v.v. Chúng là những công cụ kiểm soát luồng và RxJava tốt hơn nhiều lần.
  9. Xem LiveData như một thứ giữ dữ liệu và không có gì khác. Chúng ta cũng có thể nói LiveData là người tiêu dùng nhận biết vòng đời.

    public class RegistrationViewModel extends ViewModel {
        Disposable disposable;

        private RegistrationRepo registrationRepo;
        private MutableLiveData<RegistrationResponse> modelMutableLiveData =
                new MutableLiveData<>();

        public RegistrationViewModel() {
        }

        public RegistrationViewModel(RegistrationRepo registrationRepo) {
            this.registrationRepo = registrationRepo;
        }

        public void init(RegistrationModel registrationModel) {
            disposable = registrationRepo.loginForUser(registrationModel)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Response<RegistrationResponse>>() {
                        @Override
                        public void accept(Response<RegistrationResponse>
                                                   registrationModelResponse) throws Exception {

                            modelMutableLiveData.setValue(registrationModelResponse.body());
                        }
                    });
        }

        public LiveData<RegistrationResponse> getModelLiveData() {
            return modelMutableLiveData;
        }

       @Override
       protected void onCleared() {
                super.onCleared();
            disposable.dispose();
         }
    }

5
Xem LiveData như một thứ giữ dữ liệu và không có gì khác. ==> CÓ
Lou Morda

3
Ví dụ tốt đẹp. Bạn đã quên khai báo dùng một lần và sẽ rất tốt để xóa chúng trong onCleared.
Snicolas

Bạn có thể giải thích làm thế nào sốngata là đồng bộ? Theo như tôi biết, chúng ta có thể gửi đối tượng Livingata đến một luồng khác và sau đó luồng đó có thể định giá trị mà người quan sát có thể nghe trong MainThread.
Hitesh Bisht

Nếu bạn đọc lại những gì tôi đã viết, điều đó có nghĩa là bạn không thể làm việc trên một chủ đề khác (CÓ, tôi đã sử dụng "ngay cả" ngay cả khi sử dụng LiveData như bạn có thể sử dụng RxJava
Abhishek Kumar

Không phải vòng đời là một điểm khác biệt lớn cho LiveData? Bạn 1. mô tả những gì đường ống của bạn cần làm và kết quả cuối cùng của bạn là gì, 2. đăng ký kết quả trong các mệnh đề "quan sát", và sau đó 3. đường ống chỉ được vận hành nếu trạng thái vòng đời của bạn cho phép.
Srg

29

Trong thực tế, LiveData không phải là một công cụ cơ bản khác nhau để RxJava, vì vậy tại sao nó giới thiệu như là một thành phần kiến trúc khi RxJavacó thể dễ dàng quản lý vòng đời bằng cách lưu trữ tất cả các mục đăng ký để quan sát trong một CompositeDispoable đối tượng và sau đó xử lý chúng trong onDestroy() các Activity hoặc onDestroyView() củaFragment chỉ sử dụng một dòng mã?

Tôi đã trả lời đầy đủ cho câu hỏi này bằng cách xây dựng một ứng dụng tìm kiếm phim một lần bằng RxJava và sau đó sử dụng LiveData tại đây .

Nhưng trong ngắn hạn, có, nó có thể, nhưng điều đó trước tiên cần phải ghi đè các phương pháp vòng đời có liên quan bên cạnh kiến ​​thức vòng đời cơ bản. Điều này vẫn có thể không có ý nghĩa đối với một số người, nhưng thực tế là theo một trong các phiên Jetpack trong Google I / O 2018 nhiều nhà phát triển thấy phức tạp quản lý vòng đời. Các lỗi sự cố phát sinh do không xử lý sự phụ thuộc vào vòng đời có thể là một dấu hiệu khác cho thấy một số nhà phát triển, ngay cả khi có kiến ​​thức về vòng đời, quên mất việc xử lý nó trong mọi Hoạt động / Đoạn họ sử dụng trong ứng dụng của mình. Trong các ứng dụng lớn, điều này có thể trở thành một vấn đề, bất chấp ảnh hưởng tiêu cực của nó đến năng suất.

Điểm mấu chốt là bằng cách giới thiệu LiveData, số lượng lớn hơn các nhà phát triển dự kiến ​​sẽ áp dụng MVVM mà không cần phải hiểu quản lý vòng đời, rò rỉ bộ nhớ và sự cố. Mặc dù tôi không nghi ngờ gì LiveDatalà không thể so sánh RxJavavề khả năng và sức mạnh mà nó mang lại cho các nhà phát triển, lập trình phản ứng và RxJavalà một khái niệm và công cụ khó hiểu đối với nhiều người. Mặt khác, tôi không nghĩ LiveDatanó có nghĩa là một sự thay thế cho RxJavađơn giản là không thể, nhưng là một công cụ rất đơn giản để xử lý một vấn đề phổ biến gây tranh cãi mà nhiều nhà phát triển gặp phải.

** CẬP NHẬT ** Tôi đã thêm một bài viết mới ở đây , nơi tôi đã giải thích việc lạm dụng LiveData có thể dẫn đến kết quả không mong muốn như thế nào. RxJava có thể đến giải cứu trong những tình huống này



2
"tại sao là nó đưa ra khi RxJava có thể dễ dàng quản lý vòng đời bằng cách lưu trữ tất cả các mục đăng ký trong một CompositeDispoable và sau đó xử lý chúng trong onDestroy () của hoạt động" - LiveDatasẽ định đoạt trong onStopthực tế
arekolek

@arekolek theo hiểu biết của tôi: ngay cả để xử lý CompositeDispoablewe cũng đã ghi đè lên các phương thức vòng đời. Nhưng trong dữ liệu trực tiếp, tất cả sẽ bao gồm trong một dòng mã. Vì vậy, chúng tôi đang tiết kiệm tối thiểu 20 dòng mã.
Suresh

Chúng ta có thể định nghĩa phương thức BaseFragment và định nghĩa phương thức đăng ký [] () được ghi đè bằng tất cả các đoạn có nguồn gốc, gọi phương thức này trong onCreateView và thêm giá trị trả về trong CompositeDis Dùng một lần, bỏ qua trong onDestroyView, không quên nữa.
android2013

Đó không chỉ là về việc xử lý. Sử dụng RxJava, bạn phải xử lý tại onStop, sau đó đăng ký lại trong onStart / onResume, xử lý các thay đổi cấu hình và thực hiện một loạt các công cụ khác. Đó là lý do tại sao có quá nhiều sự cố khi sử dụng RxJava. LiveData xử lý tất cả những thứ đó, nhưng không linh hoạt như RxJava.
dùng932178

24

Như bạn có thể biết trong hệ sinh thái phản ứng, chúng ta có một Đài quan sát phát ra dữ liệu và một Người quan sát đăng ký (được thông báo) về phát xạ quan sát này, không có gì lạ là cách thức hoạt động của cái gọi là Mẫu quan sát. Một "tiếng hét" có thể quan sát được một cái gì đó, Người quan sát được thông báo rằng Đài quan sát có thể hét lên một cái gì đó trong một thời điểm nhất định.

Hãy suy nghĩ LiveDatanhư một Đài quan sát cho phép bạn quản lý các Quan sát viên đang ở activetrạng thái. Nói cách khác LiveDatalà một quan sát đơn giản nhưng cũng chăm sóc vòng đời.

Nhưng hãy xem hai trường hợp mã bạn yêu cầu:

A) Dữ liệu trực tiếp

B) RXJava

A) Đây là một triển khai cơ bản của LiveData

1) bạn thường khởi tạo LiveData trong ViewModel để duy trì thay đổi hướng (bạn có thể có LiveData chỉ đọc hoặc MutableLiveData có thể ghi được, vì vậy bạn thường phơi ra bên ngoài lớp LiveData)

2) trong OnCreatephương thức Hoạt động chính (không phải ViewModel), bạn "đăng ký" một đối tượng Người quan sát (thường là phương thức onChanged)

3) bạn khởi chạy phương thức quan sát để thiết lập liên kết

Đầu tiên ViewModel(sở hữu logic kinh doanh)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

Và đây là MainActivity(càng ngu ngốc càng tốt)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val ViewModelProvider= ViewModelProviders.of(this).get(ViewModel::class.java)

        ViewModelProvider.observe(this, Observer {//Points 2 and 3
            //what you want to observe
        })


        }
    }
}

B) Đây là triển khai cơ bản của RXJava

1) bạn tuyên bố một quan sát

2) bạn khai báo một Người quan sát

3) bạn đăng ký Đài quan sát với Người quan sát

Observable.just(1, 2, 3, 4, 5, 6) // Point 1

   .subscribe(new Subscriber() {    //Points 2 & 3
       @Override
       public void onCompleted() {
           System.out.println("Complete!");
       }

       @Override
       public void onError(Throwable e) {
       }

       @Override
       public void onNext(Double value) {
           System.out.println("onNext: " + value);
       }
    });

Đặc biệt LiveDatađược sử dụng với Lifecyclevà thường với ViewModel(như chúng ta đã thấy) các thành phần kiến ​​trúc. Trong thực tế khi LiveDatađược kết hợp với ViewModel cho phép bạn cập nhật theo thời gian thực mọi thay đổi trong Trình quan sát, để các sự kiện được quản lý theo thời gian thực khi cần thiết. Để sử dụng, chúng LiveDatatôi khuyên bạn nên biết khái niệm về vòng đời và các đối tượng tương đối LifeCycleOwner / LifeCycle , tôi cũng khuyên bạn nên xem Biến đổi , nếu bạn muốn thực hiện LiveDatatrong các tình huống thực tế. Ở đây bạn có thể tìm thấy một số trường hợp sử dụng từ commonsware tuyệt vời .

Để gói gọn về cơ bảnLiveDatalà một cách đơn giảnRXJava, một cách thanh lịch để quan sát các thay đổi trên nhiều thành phần mà không tạo ra các quy tắc phụ thuộc rõ ràng như vậy giữa các thành phần, để bạn có thể kiểm tra mã dễ dàng hơn nhiều và dễ đọc hơn nhiều. RXJava, cho phép bạn thực hiện những điều của LiveData và nhiều hơn nữa. Do các chức năng mở rộng của RXJava, bạn có thể sử dụng LiveData cho các trường hợp đơn giản hoặc khai thác tất cả sức mạnh của RXJava khi sử dụng các thành phần Kiến trúc Android như ViewModel , tất nhiên điều này có nghĩa làRXJavacó thể phức tạp hơn nhiều, chỉ cần nghĩ rằng có hàng trăm nhà khai thác thay thế của SwitchMap và Bản đồ của LiveData (tại thời điểm này).

RXJava phiên bản 2 là một thư viện đã cách mạng hóa mô hình Hướng đối tượng, thêm một cách gọi là chức năng để quản lý luồng chương trình.


4

LiveData là tập hợp con của các thành phần kiến ​​trúc Android được phát triển bởi nhóm Android.

Với dữ liệu trực tiếp và các thành phần kiến ​​trúc khác, rò rỉ bộ nhớ và các vấn đề tương tự khác được xử lý bởi các thành phần kiến ​​trúc. Vì nó được phát triển bởi đội ngũ android, nó là tốt nhất cho Android. Họ cũng cung cấp các bản cập nhật xử lý các phiên bản mới của Android.

Nếu bạn chỉ muốn sử dụng trong phát triển ứng dụng Android, hãy tìm các thành phần kiến ​​trúc Android. Mặt khác, nếu bạn muốn sử dụng ứng dụng Java khác, như ứng dụng web, ứng dụng máy tính để bàn, v.v., hãy sử dụng RxJava


Tôi đã cố gắng làm rõ câu trả lời của bạn. Nếu tôi có bất kỳ mâu thuẫn nào với mục đích ban đầu của bạn, vui lòng chỉnh sửa. Nếu bạn làm như vậy, xin vui lòng cố gắng làm cho nó rõ ràng hơn so với sửa đổi ban đầu. Phần cuối câu trả lời của bạn thành thật không có ý nghĩa.
Zoe

2

LiveDatanhư một thứ giữ dữ liệu và không có gì khác. Chúng ta cũng có thể nói LiveData là người tiêu dùng nhận biết Vòng đời. LiveDataChúng tôi khuyên bạn nên biết khái niệm về vòng đời và các đối tượng tương đối LifeCycleOwner / LifeCycle, bạn có được các khả năng chuyển đổi và truyền phát cho logic nghiệp vụ và hoạt động nhận biết vòng đời cho UI của bạn.

Rx là công cụ mạnh mẽ cho phép giải quyết vấn đề theo phong cách khai báo thanh lịch. Nó xử lý các tùy chọn bên kinh doanh hoặc hoạt động Api dịch vụ


0

So sánh LiveData với RxJava là so sánh táo với salad trái cây.

So sánh LiveData với ContentObserver và bạn đang so sánh táo với táo. LiveData thực sự là một sự thay thế nhận biết vòng đời cho ContentObserver.

So sánh RxJava với AsyncTask hoặc bất kỳ công cụ xâu chuỗi nào khác là so sánh xà lách trái cây với cam, bởi vì RxJava giúp nhiều hơn là chỉ xâu chuỗi.


0
  • LiveData một phần bằng với Chủ đề Rx hoặc SharedRxObservable

  • LiveData quản lý vòng đời của thuê bao nhưng đăng ký Rx Tiêu đề nên được tạo và xử lý thủ công

  • LiveData không có trạng thái chấm dứt nhưng Chủ đề Rx có OnError và OnCompleted

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.