How can we "assign" LiveData from Room to MutableLiveData, within ViewModel

The trick is to not do any of the actual fetching in the view model.

Getting data, be it from network or database, should be done in the repository. The ViewModel should be agnostic in this regard.

In the ViewModel, use the LiveData class, not MutableLiveData. Unless you really find a use case for it.

// In your constructor, no extra thread
notesLiveData = notesLiveDataFromRepository.getAllNotes();

Then in your repository you can have the logic in the getAllNotes() method for determining where those notes are coming from. In the repository you have the MutableLiveData. You can then postValue to that, from a thread that is getting the data. That isn't necessary for room though, that is handled for you.

So in your repository you would have another LiveData being returned that is backed directly from a DAO method.

In that case, you need to stick with public abstract LiveData<List<Note>> getNotes();.

Activity

public class MyActivity extends AppCompatActivity {

    private MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set up your view model
        viewModel = ViewModelProviders.of(this).get(MyViewModel.class);

        // Observe the view model
        viewModel.getMyLiveData().observe(this, s -> {
            // You work with the data provided through the view model here.
            // You should only really be delivering UI updates at this point. Updating
            // a RecyclerView for example.
            Log.v("LIVEDATA", "The livedata changed: "+s);
        });

        // This will start the off-the-UI-thread work that we want to perform.
        MyRepository.getInstance().doSomeStuff();
    }
}

ViewModel

public class MyViewModel extends AndroidViewModel {

    @NonNull
    private MyRepository repo = MyRepository.getInstance();

    @NonNull
    private LiveData<String> myLiveData;

    public MyViewModel(@NonNull Application application) {
        super(application);
        // The local live data needs to reference the repository live data
        myLiveData = repo.getMyLiveData();
    }

    @NonNull
    public LiveData<String> getMyLiveData() {
        return myLiveData;
    }
}

Repository

public class MyRepository {

    private static MyRepository instance;

    // Note the use of MutableLiveData, this allows changes to be made
    @NonNull
    private MutableLiveData<String> myLiveData = new MutableLiveData<>();

    public static MyRepository getInstance() {
        if(instance == null) {
            synchronized (MyRepository.class) {
                if(instance == null) {
                    instance = new MyRepository();
                }
            }
        }
        return instance;
    }

    // The getter upcasts to LiveData, this ensures that only the repository can cause a change
    @NonNull
    public LiveData<String> getMyLiveData() {
        return myLiveData;
    }

    // This method runs some work for 3 seconds. It then posts a status update to the live data.
    // This would effectively be the "doInBackground" method from AsyncTask.
    public void doSomeStuff() {
        new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException ignored) {
            }

            myLiveData.postValue("Updated time: "+System.currentTimeMillis());
        }).start();
    }

}

Very simple.

class MainViewModel: ViewModel() {

    @Inject lateinit var currencyRepository: CurrencyRepository

    val notifyCurrencyList = MediatorLiveData<List<Currency?>>()

    init {
        CurrencyApplication.component.inject(this)
    }

    fun loadCurrencyList() {
        notifyCurrencyList.addSource(currencyRepository.loadLatestRates()) {
            notifyCurrencyList.value = it
        }
    }


}