You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MVVM架构,如何用RxJava从Room数据库获取数据

Implementing RxJava Data Fetch with Room in MVVM

Hey there! Let's get your RxJava-based data fetching up and running with Room in your MVVM setup. Here's a step-by-step breakdown of the changes you need to make:

1. Refine the UserRepository

First, let's add a method to expose the user data stream, and fix a small anti-pattern (your repo shouldn't handle UI like Toasts—we'll move that responsibility to the ViewModel/View later):

public class UserRepository {
    private UserDb userDb;
    private UserDao userDao;
    private Flowable<List<User>> allUsers;

    public UserRepository(Application application) {
        userDb = UserDb.getInstance(application);
        userDao = userDb.userDao();
        // Configure thread scheduling for the data stream
        allUsers = userDao.getAllUsers()
                .subscribeOn(Schedulers.io()) // Run DB operations on background thread
                .observeOn(AndroidSchedulers.mainThread()); // Deliver results to main thread for UI updates
    }

    // Let the caller handle success/error by passing an observer
    public void insert(final User user, CompletableObserver observer){
        Completable.fromAction(() -> userDao.insert(user))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    // Expose the user data stream to ViewModel
    public Flowable<List<User>> getAllUsers() {
        return allUsers;
    }
}

Key Notes:

  • We removed the Context reference from the repo—keeping UI logic out of repositories follows the single responsibility principle.
  • The insert method now accepts a CompletableObserver, so the ViewModel can handle success/error notifications instead of the repo.

2. Update the ViewModel to Expose Data to the View

Next, modify your MainActivityViewModel to hold the user data stream and manage subscriptions safely:

public class MainActivityViewModel extends AndroidViewModel {
    private UserRepository repos;
    private Flowable<List<User>> allUsers;
    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    public MainActivityViewModel(@NonNull Application application) {
        super(application);
        repos = new UserRepository(application);
        allUsers = repos.getAllUsers();
    }

    // Expose the user stream for the Activity/Fragment to subscribe to
    public Flowable<List<User>> getAllUsers() {
        return allUsers;
    }

    public void insertUser(User user, Context context) {
        CompletableObserver observer = new CompletableObserver() {
            @Override
            public void onSubscribe(Disposable d) {
                compositeDisposable.add(d); // Track the disposable to avoid memory leaks
            }

            @Override
            public void onComplete() {
                Toast.makeText(context, "Data inserted", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        };
        repos.insert(user, observer);
    }

    // Clean up all subscriptions when ViewModel is destroyed
    @Override
    protected void onCleared() {
        super.onCleared();
        compositeDisposable.dispose();
    }
}

Key Notes:

  • We use a CompositeDisposable to track active subscriptions—this ensures no lingering connections when the ViewModel is destroyed.
  • The ViewModel now handles UI feedback like Toasts, which is a more appropriate home for this logic.

3. Subscribe to Data in Your Activity

Finally, connect your ViewModel to the Activity to display and react to data changes:

public class MainActivity extends AppCompatActivity {
    private MainActivityViewModel viewModel;
    private CompositeDisposable activityDisposables = new CompositeDisposable();
    private UserAdapter userAdapter; // Assume you have a RecyclerView adapter

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize ViewModel
        viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);

        // Set up your RecyclerView and adapter here...

        // Subscribe to the user data stream
        Disposable userDisposable = viewModel.getAllUsers()
                .subscribe(users -> {
                    // Update UI with the latest user list
                    userAdapter.submitList(users);
                }, throwable -> {
                    // Handle loading errors
                    Toast.makeText(this, "Failed to load users: " + throwable.getMessage(), Toast.LENGTH_SHORT).show();
                });

        activityDisposables.add(userDisposable);
    }

    // Example: Trigger user insertion (e.g., from a button click)
    private void addSampleUser() {
        User newUser = new User("Jane Smith", "jane@example.com");
        viewModel.insertUser(newUser, this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        activityDisposables.dispose(); // Clean up activity-level subscriptions
    }
}

Key Notes:

  • Room's Flowable<List<User>> automatically emits a new list every time the Users table is updated (insert, update, delete)—perfect for reactive UI updates.
  • RxJava's thread operators ensure database work stays off the main thread, keeping your app responsive.

Why This Works:

This setup follows MVVM best practices:

  • Repositories handle raw data operations with Room and RxJava.
  • ViewModels manage business logic and expose data streams to the UI.
  • Views subscribe to these streams to render updates and handle user interactions.

内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:45:51