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.
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 .
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With