question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GithubBrowserSample: demonstrate a way to communicate among ViewModels

See original GitHub issue

Hi!

I was looking at a way for one ViewModel to access another ViewModel and see if there any good practice to do so. Unfortunately (unless I just didn’t find it) this sample doesn’t demonstrate a way to do this.

The ViewModel guide talks about how you can “Share Data Between Fragments” with a “shared ViewModel” but with no sample of how to share data between ViewModels.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

8reactions
palto-blubekcommented, Aug 1, 2017

I’m not sure why you’re saying this is not the purpose of ViewModel. They allow to separate UI logic from other kinds of logic. In that sense, you could have one piece in one ViewModel that depends on something that is in another one.

For instance: let’s say you have a “search query” fragment where the user can fill some criteria. Then you have a results fragment. But you also want a “search summary” fragment, that shows some info about the search, including the query that comes from the “search query” fragment. To do that, the “search summary” ViewModel needs to observe some objects that are managed by the “search query” ViewModel.

3reactions
Guang1234567commented, Aug 20, 2018

[Question] is below:

but with no sample of how to share data between ViewModels.

Nobody has been answer… ((유∀유|||))

@BoD

Share data between ViewModels is hard! Not only conside share data but also have to manage the viewmodels’s lifecycle!

My way to share data between ViewModels that in the same activity or fragment:

class GroupViewModels extends ViewModel {
   private A_ViewModel aVM;
   private B_ViewModel bVM;

   priavte BehSubject<Boolean> killSwitcher;

  public GroupViewModels (...) {
    aVM = new A_ViewModel(...);
    bVM = new B_ViewModel(...);

   killSwitcher= BehaviorSubject.create();
 }

public void onClear() {
    killSwitcher.onNext(Boolean.TRUE);
    aVM.onClear();
    bVM.onClear();
}

 public Observable<Event> OnNextEvent () {
  return aVM.OnNextEvent().flatMap(new Function<...>() {
    // dosth;
    returen bVM.OnNextEvent();
  })
  .takeUntil(killSwitcher);
}

....

or

Way 2:


class GroupViewModels extends ViewModel {
   private A_ViewModel aVM;
   private B_ViewModel bVM;

   priavte BehSubject<Boolean> killSwitcher;

  public GroupViewModels (A_ViewModel a, B_ViewModel  b) {
    aVM = a;
    bVM = b;

    // share data between ViewModels. eg:
    //a.subcribe(b);
   // b.subcribe(a);

   killSwitcher= BehaviorSubject.create();
 }

public void onClear() {
    killSwitcher.onNext(Boolean.TRUE);

    // don not need to call onClear() !!!
    // aVM.onClear();
    // bVM.onClear();
}

public Observable<Event> OnNextEvent () {
  return aVM.OnNextEvent().flatMap(new Function<...>() {
    // share data between ViewModels.
    returen bVM.OnNextEvent();
  })
  .takeUntil(killSwitcher);
}


public abstract class ShareViewModelFactory implements ViewModelProvider.Factory {

    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> mCreators;

    public ShareViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
        mCreators = creators;
        mShareCache = new HashMap<>();
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        Provider<? extends ViewModel> creator = mCreators.get(modelClass);
        if (creator == null) {
            for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : mCreators.entrySet()) {
                if (modelClass.isAssignableFrom(entry.getKey())) {
                    creator = entry.getValue();
                    break;
                }
            }
        }

        if (creator == null) {
            throw new IllegalArgumentException("unknown model class " + modelClass);
        }

        try {
            return (T) creator.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}



// Usage: 

class XXXActivity {
  public void onCreate() {
      Map<Class<? extends ViewModel>, Provider<ViewModel>> creators = new HashMap<>();
      final ViewModelProvider.Factory factory = new ShareViewModelFactory(creators);

      creators.put(A_ViewModel.class, ...);
      creators.put(B_ViewModel.class, ...);
    
      creators.put(GroupViewModels.class, new Provider<ViewModel>() {
             ViewModel get() {
                 return new GroupViewModel(
                              ViewModelProvider.of(XXXActivity.this, factory).get(A_ViewModel.class),
                              ViewModelProvider.of(XXXActivity.this, factory).get(B_ViewModel.class),
                 )
             }
     } );

    GroupViewModels gVm= ViewModelProvider.of(XXXActivity.this, factory).get(GroupViewModels .class);
  }
}

Warning:

No circular reference like below, please!

 GroupViewModels(A_ViewModel a, B_ViewModel b);

A_ViewModel (GroupViewModels g);

B_ViewModel (GroupViewModels g)

Read more comments on GitHub >

github_iconTop Results From Across the Web

GithubBrowserSample: demonstrate a way to communicate ...
My way to share data between ViewModels that in the same activity or fragment: class GroupViewModels extends ViewModel { private A_ViewModel aVM ...
Read more >
How to share view models between fragments using Google's ...
by viewModels() provides a ViewModel that is scoped to the individual Fragment. There's a separate by activityViewModels() that scopes the ...
Read more >
ViewModels and LiveData: Patterns + AntiPatterns - Medium
The recommended way to communicate between ViewModels and Views is the observer pattern, using LiveData or observables from other libraries.
Read more >
Encapsulating View State - Ryan Harter
Let's take a look at a simple approach to communication between the ViewModel and the view layer that allows us to have dead...
Read more >
Android MVVM — A synchronized way of communication.
enqueueCommand(): is what the view models calls to put a command in its queue to be emitted in time. The “flags” here makes...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found