Trying basic MVVM implementation based on https://github.com/mitchtabian/MVVMExample1
This commit is contained in:
		| @@ -82,17 +82,6 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter. | ||||
|         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() { | ||||
|         return sortRule; | ||||
|     } | ||||
|   | ||||
| @@ -25,6 +25,7 @@ import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.AppCompatImageButton; | ||||
| @@ -35,6 +36,7 @@ import androidx.core.view.GravityCompat; | ||||
| import androidx.drawerlayout.widget.DrawerLayout; | ||||
| import androidx.fragment.app.FragmentManager; | ||||
| import androidx.fragment.app.FragmentTransaction; | ||||
| import androidx.lifecycle.ViewModelProvider; | ||||
| import androidx.preference.PreferenceManager; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 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.SORT_BY_CREATED; | ||||
| 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_EDIT = 200; | ||||
| @@ -84,9 +87,9 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|     private StaggeredGridLayoutManager layoutManager; | ||||
|     private FloatingActionButton fab; | ||||
|  | ||||
|     private MainPresenter presenter; | ||||
|     private GeofavoriteAdapter geofavoriteAdapter; | ||||
|     private ItemClickListener rvItemClickListener; | ||||
|     private MainActivityViewModel mMainActivityViewModel; | ||||
|  | ||||
|     NavigationAdapter navigationCommonAdapter; | ||||
|  | ||||
| @@ -95,6 +98,8 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_main); | ||||
|  | ||||
|         mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); | ||||
|         mMainActivityViewModel.init(); | ||||
|         preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); | ||||
|  | ||||
|         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); | ||||
|         recyclerView.setLayoutManager(layoutManager); | ||||
|  | ||||
|         presenter = new MainPresenter(this); | ||||
|  | ||||
|         rvItemClickListener = new ItemClickListener() { | ||||
|             @Override | ||||
|             public void onItemClick(Geofavorite item) { | ||||
| @@ -133,7 +136,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|         geofavoriteAdapter.setSortRule(sortRule); | ||||
|  | ||||
|         swipeRefresh = findViewById(R.id.swipe_refresh); | ||||
|         swipeRefresh.setOnRefreshListener(() -> presenter.getGeofavorites()); | ||||
|         swipeRefresh.setOnRefreshListener(() -> updateGeofavorites()); | ||||
|  | ||||
|         fab = findViewById(R.id.add); | ||||
|         fab.setOnClickListener(view -> addGeofavorite()); | ||||
| @@ -190,7 +193,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|         super.onStart(); | ||||
|  | ||||
|         // Update list | ||||
|         presenter.getGeofavorites(); | ||||
|         mMainActivityViewModel.getGeofavorites().observe(this, this); | ||||
|     } | ||||
|  | ||||
|     private void setupNavigationMenu() { | ||||
| @@ -239,9 +242,9 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|     public void onActivityResult(int requestCode, int resultCode, Intent data) { | ||||
|         super.onActivityResult(requestCode, resultCode, data); | ||||
|         if (requestCode == INTENT_ADD && resultCode == RESULT_OK) { | ||||
|             presenter.getGeofavorites(); | ||||
|             mMainActivityViewModel.getGeofavorites().observe(this, this); | ||||
|         } 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); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void showLoading() { | ||||
|         swipeRefresh.setRefreshing(true); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void hideLoading() { | ||||
|         swipeRefresh.setRefreshing(false); | ||||
|     } | ||||
|  | ||||
|     @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 | ||||
| //    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 | ||||
|     public void onSortingOrderChosen(int sortSelection) { | ||||
| @@ -328,7 +308,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|                 .setTitle(R.string.dialog_delete_title) | ||||
|                 .setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() { | ||||
|                     public void onClick(DialogInterface dialog, int id) { | ||||
|                         presenter.deleteGeofavorite(item.getId()); | ||||
|                         // TODO presenter.deleteGeofavorite(item.getId()); | ||||
|                         dialog.dismiss(); | ||||
|                         // Callback is onGeofavoriteDeleted | ||||
|                     } | ||||
| @@ -348,4 +328,26 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user