0

In the Guide to app architecture by Google there is an example, which I do not understand -

UserProfileViewModel:

public class UserProfileViewModel extends ViewModel {
    private LiveData<User> user;
    public LiveData<User> getUser() {
        return user;
    }
}

UserProfileFragment:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    viewModel.getUser().observe(this, user -> {
      // Update UI.
    });
}

When I look at the LiveData reference, there is only the following observe method:

observe(LifecycleOwner owner, Observer<T> observer)

I am confused, that the method signature does not match:

The LifecycleOwner is the support library Fragment, all right.

But how can the expression user-> { some code } be an Observer object?

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
  • 3
    That is a Java 8 lambda expression, which the compiler will convert into an implementation of the `Observer` interface. – CommonsWare Oct 21 '18 at 15:04
  • What does `user` mean then in that implementation of the interface? – Alexander Farber Oct 21 '18 at 15:05
  • 2
    That is a `User`. The lambda expression will be converted into an `Observer`, since this is a `LiveData`, and the `User` is passed into the `onChanged()` method formed from the body of the lambda expression. – CommonsWare Oct 21 '18 at 15:06
  • 3
    Observer has a [single abstract method](https://stackoverflow.com/q/23342499/3788176), and thus it can be instantiated with a lambda. – Andy Turner Oct 21 '18 at 15:06
  • I still do not understand, why it is not `User -> { some code }` then... – Alexander Farber Oct 21 '18 at 15:10
  • 1
    @AlexanderFarber in fact it is, it is `User user -> { some code }` – Ovi Trif Oct 21 '18 at 15:17
  • Thanks, but `private User user;` is defined in `UserProfileViewModel` and not in `UserProfileFragment` where the `user -> { some code }` expression is used... so how does compiler know that `user` is a `User` instance? – Alexander Farber Oct 21 '18 at 15:21
  • 2
    @AlexanderFarber, The code is `viewModel.getUser().observe(this, user -> { ... })`. The return type of `getUser()` is `LiveData `. `getUser()` is public. And, for clearance, `user -> { some code }` has nothing to do with the member `user` in terms of member name. It can be named anything, for example `u -> { ... }` would be pretty much the same. The type though, it's always `User` in this case. – Ovi Trif Oct 21 '18 at 15:25

1 Answers1

3

The expression user-> { some code } is a SAM (Single Abstract Method) type, more info in this stack overflow post.

In short it is just syntactic sugar for:

viewModel.getUser().observe(this, new Observer<User>() {
    @Override
    public void onChanged(@Nullable User user) {
        // Some code
    }
});
Ovi Trif
  • 394
  • 4
  • 11