Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues accessing ViewModel and observing LiveData in views #74

Open
MatthAddax opened this issue Mar 19, 2018 · 5 comments
Open

Issues accessing ViewModel and observing LiveData in views #74

MatthAddax opened this issue Mar 19, 2018 · 5 comments

Comments

@MatthAddax
Copy link

Hi,

I've been trying to access viewmodel and livedata in my views using Magellan but it don't work.

Am I missing something?

I tryed to access the ViewModel this way
MyViewModel = ViewModelProviders.of((LifeCycleOwner)getScreen().getActivity()).get(MyViewModel.class);

But it keep telling me that I can't call virtual method "getActivity()" from null object reference.

Does anyone else have the same problem as me?

Thank you for your help,
Cordially,
Matthieu

@fabiendevos
Copy link
Contributor

fabiendevos commented Mar 20, 2018

Hi Matthieu,

First of all, Magellan has not be designed to work well with ViewModel and LiveData (it was created before those even existed). So anything you are trying to do there is unsupported for now.

With that being said, getActivity() definitely returns your single Activity. Can you share more of your code? How are you initializing Magellan, where do you call getActivity()? (getActivity() returns null until createView() is called)

@MatthAddax
Copy link
Author

MatthAddax commented Mar 20, 2018

Hi,

Here is the way I initialized Magellan. Everything seemed to work well, is that what I'm concerned about, nothing should have gone wrong.

Parent activity
`public class NewInterventionFlow extends SingleActivity {

@BindView(R.id.intervention_flow_toolbar)Toolbar toolbar;

@Override
protected Navigator createNavigator() {
    return Navigator.withRoot(new StepOneScreen()).build();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_intervention_flow);
    ButterKnife.bind(this);

    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    assert actionBar!=null;
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_black_24dp);
}

}`

StepOneScreen
public class StepOneScreen extends Screen<StepOneView>{ @Override protected StepOneView createView(Context context) { return new StepOneView(context); } }

StepOneScreen
`public class StepOneView extends BaseScreenView {
@BindView(R.id.company_autocomplete)AutoCompleteTextView companyAutocomplete;
@BindView(R.id.contact_autocomplete)AutoCompleteTextView contactAutocomplete;
@BindView(R.id.intervention_date)TextView interventionDate;

public StepOneView(Context context) {
    super(context);
    inflate(context, R.layout.view_intervention_step_one, this);
    ButterKnife.bind(this);
    

   /*How I initialize the viewmodel */
   MyViewModel viewModel = ViewModelProviders.of(((LifecycleOwner)getScreen().getActivity())).get(MyViewModel.class);

}

}`

This always failed because I tried to access a null object. Either the screen or the returned activity are nulls. When I tried to create my viewmodel directly in the activity and then get the viewmodel from the activity (always by going through getScreen().getActivity() I got the same, can't access null reference.

By the way are there any plans to "adapt" Magellan to the new architecture components? I have the feeling this combination could make powerful application flows.

Thank you :)

@fabiendevos
Copy link
Contributor

@MatthAddax ,

While you are creating the view, the screen is not yet attached to it so you can't call getScreen. But the context you get is you Activity! So you should be able to just do ViewModelProviders.of((LifecycleOwner)context).get(MyViewModel.class);

Let me know if this works.

That being said, the point of ViewModel is to retain your Model across Activity configuration changes like rotation. With Magellan, the Screen already survives rotation so you can simply store your data in a simple member variable of the Screen.

I don't know much about Arch components ViewModel so maybe there is some other good reason to use them.

I do plan to look into them more and see if there is a way to "adapt" magellan to them, but they solve similar problems, so not sure yet if this will make sense.

@Zhuinden
Copy link

Zhuinden commented Apr 12, 2018

But the context you get is you Activity!

If it's the View's context, then sometimes it's ContextThemeWrapper, you know.

https://stackoverflow.com/a/21673721/2413303

@fabiendevos
Copy link
Contributor

fabiendevos commented Apr 14, 2018

@Zhuinden in this case, you get the context from Magellan and it's an Activity (strongly typed to it) all the way until the very end (createVIew being called) so you are actually guaranteed that this will be an Activity.

I chose to make it a Context in the type to discourage manipulating the Activity from there (all you should need is a Context), but if you must, casting is safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants