Trying basic MVVM implementation based on https://github.com/mitchtabian/MVVMExample1
This commit is contained in:
parent
b9dbde7f7c
commit
cf7f96efad
@ -82,17 +82,6 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
return geofavoriteListFiltered.get(position);
|
return geofavoriteListFiltered.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeById(int id) {
|
|
||||||
for (Geofavorite g : geofavoriteList) {
|
|
||||||
if (g.getId() == id) {
|
|
||||||
geofavoriteList.remove(g);
|
|
||||||
geofavoriteListFiltered.remove(g);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSortRule() {
|
public int getSortRule() {
|
||||||
return sortRule;
|
return sortRule;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.AppCompatImageButton;
|
import androidx.appcompat.widget.AppCompatImageButton;
|
||||||
@ -35,6 +36,7 @@ import androidx.core.view.GravityCompat;
|
|||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||||
@ -61,8 +63,9 @@ import static android.view.View.VISIBLE;
|
|||||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.*;
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.*;
|
||||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
||||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements MainView, OnSortingOrderListener {
|
public class MainActivity extends AppCompatActivity implements OnSortingOrderListener {
|
||||||
|
|
||||||
private static final int INTENT_ADD = 100;
|
private static final int INTENT_ADD = 100;
|
||||||
private static final int INTENT_EDIT = 200;
|
private static final int INTENT_EDIT = 200;
|
||||||
@ -84,9 +87,9 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
private StaggeredGridLayoutManager layoutManager;
|
private StaggeredGridLayoutManager layoutManager;
|
||||||
private FloatingActionButton fab;
|
private FloatingActionButton fab;
|
||||||
|
|
||||||
private MainPresenter presenter;
|
|
||||||
private GeofavoriteAdapter geofavoriteAdapter;
|
private GeofavoriteAdapter geofavoriteAdapter;
|
||||||
private ItemClickListener rvItemClickListener;
|
private ItemClickListener rvItemClickListener;
|
||||||
|
private MainActivityViewModel mMainActivityViewModel;
|
||||||
|
|
||||||
NavigationAdapter navigationCommonAdapter;
|
NavigationAdapter navigationCommonAdapter;
|
||||||
|
|
||||||
@ -95,6 +98,8 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
|
||||||
|
mMainActivityViewModel.init();
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
|
||||||
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
||||||
@ -104,8 +109,6 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
layoutManager = new StaggeredGridLayoutManager(gridViewEnabled ? 2 : 1, StaggeredGridLayoutManager.VERTICAL);
|
layoutManager = new StaggeredGridLayoutManager(gridViewEnabled ? 2 : 1, StaggeredGridLayoutManager.VERTICAL);
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
presenter = new MainPresenter(this);
|
|
||||||
|
|
||||||
rvItemClickListener = new ItemClickListener() {
|
rvItemClickListener = new ItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(Geofavorite item) {
|
public void onItemClick(Geofavorite item) {
|
||||||
@ -133,7 +136,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
geofavoriteAdapter.setSortRule(sortRule);
|
geofavoriteAdapter.setSortRule(sortRule);
|
||||||
|
|
||||||
swipeRefresh = findViewById(R.id.swipe_refresh);
|
swipeRefresh = findViewById(R.id.swipe_refresh);
|
||||||
swipeRefresh.setOnRefreshListener(() -> presenter.getGeofavorites());
|
swipeRefresh.setOnRefreshListener(() -> updateGeofavorites());
|
||||||
|
|
||||||
fab = findViewById(R.id.add);
|
fab = findViewById(R.id.add);
|
||||||
fab.setOnClickListener(view -> addGeofavorite());
|
fab.setOnClickListener(view -> addGeofavorite());
|
||||||
@ -190,7 +193,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
// Update list
|
// Update list
|
||||||
presenter.getGeofavorites();
|
mMainActivityViewModel.getGeofavorites().observe(this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupNavigationMenu() {
|
private void setupNavigationMenu() {
|
||||||
@ -239,9 +242,9 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode == INTENT_ADD && resultCode == RESULT_OK) {
|
if (requestCode == INTENT_ADD && resultCode == RESULT_OK) {
|
||||||
presenter.getGeofavorites();
|
mMainActivityViewModel.getGeofavorites().observe(this, this);
|
||||||
} else if (requestCode == INTENT_EDIT && resultCode == RESULT_OK) {
|
} else if (requestCode == INTENT_EDIT && resultCode == RESULT_OK) {
|
||||||
presenter.getGeofavorites();
|
mMainActivityViewModel.getGeofavorites().observe(this, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,35 +263,12 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showLoading() {
|
|
||||||
swipeRefresh.setRefreshing(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public void hideLoading() {
|
// public void onErrorLoading(String message) {
|
||||||
swipeRefresh.setRefreshing(false);
|
// Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
|
||||||
}
|
// Log.e(TAG, "Unable to obtain geofavorites list: " + message);
|
||||||
|
// }
|
||||||
@Override
|
|
||||||
public void onGetResult(List<Geofavorite> geofavorite_list) {
|
|
||||||
geofavoriteAdapter.setGeofavoriteList(geofavorite_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onGeofavoriteDeleted(int id) {
|
|
||||||
// Update list
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
geofavoriteAdapter.removeById(id);
|
|
||||||
Toast.makeText(MainActivity.this, R.string.list_geofavorite_deleted, Toast.LENGTH_LONG).show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onErrorLoading(String message) {
|
|
||||||
Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
|
|
||||||
Log.e(TAG, "Unable to obtain geofavorites list: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSortingOrderChosen(int sortSelection) {
|
public void onSortingOrderChosen(int sortSelection) {
|
||||||
@ -328,7 +308,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
.setTitle(R.string.dialog_delete_title)
|
.setTitle(R.string.dialog_delete_title)
|
||||||
.setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
presenter.deleteGeofavorite(item.getId());
|
// TODO presenter.deleteGeofavorite(item.getId());
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
// Callback is onGeofavoriteDeleted
|
// Callback is onGeofavoriteDeleted
|
||||||
}
|
}
|
||||||
@ -348,4 +328,26 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
startActivity(i);
|
startActivity(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateGeofavorites() {
|
||||||
|
mMainActivityViewModel.getGeofavorites().observe(this, new Observer<List<Geofavorite>>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(List<Geofavorite> geofavorites) {
|
||||||
|
geofavoriteAdapter.setGeofavoriteList(geofavorites);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: è possibile registrare un solo listener?
|
||||||
|
mMainActivityViewModel.getIsUpdating().observe(this, new Observer<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(@Nullable Boolean aBoolean) {
|
||||||
|
if(aBoolean){
|
||||||
|
swipeRefresh.setRefreshing(true);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
swipeRefresh.setRefreshing(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
||||||
|
|
||||||
|
public class MainActivityViewModel extends ViewModel {
|
||||||
|
|
||||||
|
private MutableLiveData<List<Geofavorite>> mGeofavorites;
|
||||||
|
private GeofavoriteRepository mRepo;
|
||||||
|
private MutableLiveData<Boolean> mIsUpdating = new MutableLiveData<>();
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
if (mGeofavorites != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRepo = GeofavoriteRepository.getInstance();
|
||||||
|
mGeofavorites = mRepo.getGeofavorites();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Geofavorite>> getGeofavorites(){
|
||||||
|
return mGeofavorites;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getIsUpdating(){
|
||||||
|
return mIsUpdating;
|
||||||
|
}
|
||||||
|
}
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Maps Geofavorites for Android
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2020 John Doe <john@doe.com>
|
|
||||||
* @author John Doe <john@doe.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
public class MainPresenter {
|
|
||||||
private MainView view;
|
|
||||||
|
|
||||||
public MainPresenter(MainView view) {
|
|
||||||
this.view = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getGeofavorites() {
|
|
||||||
view.showLoading();
|
|
||||||
Call<List<Geofavorite>> call = ApiProvider.getAPI().getGeofavorites();
|
|
||||||
call.enqueue(new Callback<List<Geofavorite>>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) {
|
|
||||||
((AppCompatActivity) view).runOnUiThread(() -> {
|
|
||||||
view.hideLoading();
|
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
|
||||||
view.onGetResult(response.body());
|
|
||||||
} else {
|
|
||||||
((AppCompatActivity) view).runOnUiThread(() -> {
|
|
||||||
view.hideLoading();
|
|
||||||
view.onErrorLoading(response.raw().message());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call<List<Geofavorite>> call, @NonNull Throwable t) {
|
|
||||||
((AppCompatActivity) view).runOnUiThread(() -> {
|
|
||||||
view.hideLoading();
|
|
||||||
view.onErrorLoading(t.getLocalizedMessage());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteGeofavorite(int id) {
|
|
||||||
view.showLoading();
|
|
||||||
Call<Geofavorite> call = ApiProvider.getAPI().deleteGeofavorite(id);
|
|
||||||
call.enqueue(new Callback<Geofavorite>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
|
||||||
view.hideLoading();
|
|
||||||
view.onGeofavoriteDeleted(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call<Geofavorite> call, Throwable t) {
|
|
||||||
view.hideLoading();
|
|
||||||
view.onErrorLoading(t.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Maps Geofavorites for Android
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2020 John Doe <john@doe.com>
|
|
||||||
* @author John Doe <john@doe.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
|
||||||
|
|
||||||
public interface MainView {
|
|
||||||
void showLoading();
|
|
||||||
void hideLoading();
|
|
||||||
void onGetResult(List<Geofavorite> geofavorites);
|
|
||||||
void onGeofavoriteDeleted(int id);
|
|
||||||
void onErrorLoading(String message);
|
|
||||||
}
|
|
@ -0,0 +1,56 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.repository;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton pattern
|
||||||
|
*/
|
||||||
|
public class GeofavoriteRepository {
|
||||||
|
|
||||||
|
private static GeofavoriteRepository instance;
|
||||||
|
private ArrayList<Geofavorite> dataSet = new ArrayList<>();
|
||||||
|
|
||||||
|
public static GeofavoriteRepository getInstance() {
|
||||||
|
if(instance == null){
|
||||||
|
instance = new GeofavoriteRepository();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableLiveData<List<Geofavorite>> getGeofavorites(){
|
||||||
|
// Obtain geofavorites
|
||||||
|
Call<List<Geofavorite>> call = ApiProvider.getAPI().getGeofavorites();
|
||||||
|
call.enqueue(new Callback<List<Geofavorite>>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
dataSet.addAll(response.body());
|
||||||
|
} else {
|
||||||
|
onFailure(call, new Throwable("Dataset is empty"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<List<Geofavorite>> call, @NonNull Throwable t) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MutableLiveData<List<Geofavorite>> data = new MutableLiveData<>();
|
||||||
|
data.setValue(dataSet);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user