Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM - Implementing Google Maps and having the context in ViewModel?

Tags:

android

mvvm

So I'm learning MVVM, loving it.

But.. my problem so far has been the following:

  • Implementing google maps with MVVM. (Do I do it on the activity or the viewmodel? I was only able to implement it on the activity..)

  • Especially CONTEXT.. Is it okay to pass it along like below?

I'm using this library.

This is my ViewModel:

public class DashboardViewModel implements ViewModel {

public final ObservableField<String> dashButton = new ObservableField<>("");
public final Action onRandomSearch;
private Context context;



public DashboardViewModel(Context context) {
    this.context = context;

    onRandomSearch = () -> {
        String randomString = UUID.randomUUID().toString();
        String randomQuery = randomString.substring(0, 3) + " " + randomString.substring(5, 8);
        dashButton.set(randomQuery); //JUST TO TEST
    };
}

}

This is my activity:

public class DashboardActivity extends MvvmActivity {
@NonNull
@Override
protected ViewModel createViewModel() {
    loadMap();

    return new DashboardViewModel(this);
}

@Override
protected int getLayoutId() {
    return R.layout.activity_dashboard;
}

private void loadMap() {
    SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    startLocation();

...

Now, in order to get google maps working on my application I had to implement OnMapReadyCallback, like so:

public class DashboardActivity extends MvvmActivity implements OnMapReadyCallback

I need to communicate with the method to get current location, which I implemented inside DashboardActivity..

Should I migrate the logic to get the map working inside the ViewModel?

I'm a little lost here.

like image 467
Rosenberg Avatar asked Jul 19 '17 23:07

Rosenberg


People also ask

Can ViewModel have context?

If the ViewModel needs the Application context, for example to find a system service, it can extend the AndroidViewModel class and have a constructor that receives the Application in the constructor, since Application class extends Context .

How do you pass context in ViewModel?

you can access the application context from getApplication(). getApplicationContext() from within the ViewModel. This is what you need to access resources, preferences, etc.. The ViewModel class does not have the getApplication method.

Is MVVM clean architecture?

MVVM with Clean Architecture is pretty good in such cases. It goes one step further in separating the responsibilities of your code base. It clearly abstracts the logic of the actions that can be performed in your app. Note: You can combine Clean Architecture with the model-view-presenter (MVP) architecture as well.

What is ViewModel MVVM Android?

MVVM stands for Model, View, ViewModel. Model: This holds the data of the application. It cannot directly talk to the View. Generally, it's recommended to expose the data to the ViewModel through Observables. View: It represents the UI of the application devoid of any Application Logic.


1 Answers

I was facing the same issue with SupportMapFragment in MVVM. For interim solution, i have used mapview instead of SupportMapFragment.

First you need to create one method in CustomBinding.

@BindingAdapter("initMap")
public static void initMap(final MapView mapView, final LatLng latLng) {

    if (mapView != null) {
        mapView.onCreate(new Bundle());
        mapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                // Add a marker
                googleMap.addMarker(new MarkerOptions().position(latLng).title("Marker in India"));
            }
        });
    }
}

Code for xml file

           <com.google.android.gms.maps.MapView
                android:id="@+id/map"
                android:name="com.google.android.gms.maps.MapFragment"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                app:initMap="@{viewmodel.mMapLatLngObservable}" />

And inside viewmodel class you have to take one observer field

public ObservableField<LatLng>  mMapLatLng = new ObservableField<>();

So, when you set current location in above observer variable(mMapLatLng) , your OnMapReadyCallback will be called.

like image 112
Harsh Trivedi Avatar answered Sep 21 '22 08:09

Harsh Trivedi