diff --git a/app/src/main/java/com/majinnaibu/monstercards/MonsterCardsApplication.java b/app/src/main/java/com/majinnaibu/monstercards/MonsterCardsApplication.java index 9eab6e7..ede2471 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/MonsterCardsApplication.java +++ b/app/src/main/java/com/majinnaibu/monstercards/MonsterCardsApplication.java @@ -1,7 +1,6 @@ package com.majinnaibu.monstercards; import android.app.Application; -import android.content.Context; import android.content.res.Configuration; import androidx.annotation.NonNull; @@ -14,17 +13,12 @@ import com.majinnaibu.monstercards.init.FlipperInitializer; public class MonsterCardsApplication extends Application { - private AppDatabase m_db; private MonsterRepository m_monsterLibraryRepository; public MonsterRepository getMonsterRepository() { return m_monsterLibraryRepository; } - public static MonsterCardsApplication getInstance(Context context) { - return (MonsterCardsApplication) context.getApplicationContext(); - } - public MonsterCardsApplication() { } @@ -38,9 +32,11 @@ public class MonsterCardsApplication extends Application { FlipperInitializer.init(this); - m_db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "monsters") + // .fallbackToDestructiveMigration() + AppDatabase m_db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "monsters") .addMigrations(MIGRATION_1_2) .fallbackToDestructiveMigrationOnDowngrade() +// .fallbackToDestructiveMigration() .build(); m_monsterLibraryRepository = new MonsterRepository(m_db); } diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java index f245a33..98efb35 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java @@ -18,13 +18,13 @@ import com.majinnaibu.monstercards.R; import com.majinnaibu.monstercards.data.MonsterRepository; import com.majinnaibu.monstercards.models.Monster; import com.majinnaibu.monstercards.ui.MCFragment; -import com.majinnaibu.monstercards.ui.MonsterListRecyclerViewAdapter; import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; import com.majinnaibu.monstercards.utils.Logger; import java.util.UUID; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.observers.DisposableCompletableObserver; import io.reactivex.rxjava3.schedulers.Schedulers; public class LibraryFragment extends MCFragment { @@ -46,25 +46,28 @@ public class LibraryFragment extends MCFragment { private void setupRecyclerView(@NonNull RecyclerView recyclerView) { MonsterRepository repository = this.getMonsterRepository(); - boolean mTwoPane = false; MonsterListRecyclerViewAdapter adapter = new MonsterListRecyclerViewAdapter( - this, + getContext(), repository.getMonsters(), - (monster) -> { - repository - .deleteMonster(monster) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> { + (monster) -> navigateToMonsterDetail(monster.id), + (monster) -> repository + .deleteMonster(monster) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DisposableCompletableObserver() { + @Override + public void onComplete() { Logger.logDebug("deleted"); - }, Logger::logError); - }, - mTwoPane); + } + + @Override + public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { + Logger.logError(e); + } + })); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(getContext(), (position) -> { - adapter.deleteItem(position); - })); + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(requireContext(), adapter::deleteItem)); itemTouchHelper.attachToRecyclerView(recyclerView); } @@ -76,26 +79,36 @@ public class LibraryFragment extends MCFragment { repository.addMonster(monster) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> { - Snackbar.make( - getView(), - String.format("%s created", monster.name), - Snackbar.LENGTH_LONG) - .setAction("Action", (_view) -> { - navigateToMonsterDetail(monster.id); - }) - .show(); - }, throwable -> { - Logger.logError("Error creating monster", throwable); - Snackbar.make(getView(), "Failed to create monster", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - }); - }); + .subscribe( + new DisposableCompletableObserver() { + @Override + public void onComplete() { + View view = getView(); + assert view != null; + Snackbar.make( + view, + String.format("%s created", monster.name), + Snackbar.LENGTH_LONG) + .setAction("Action", (_view) -> navigateToMonsterDetail(monster.id)) + .show(); + } + @Override + public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { + Logger.logError("Error creating monster", e); + View view = getView(); + assert view != null; + Snackbar.make(view, "Failed to create monster", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + }); + }); } protected void navigateToMonsterDetail(UUID monsterId) { NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString()); - Navigation.findNavController(getView()).navigate(action); + View view = getView(); + assert view != null; + Navigation.findNavController(view).navigate(action); } } diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/MonsterListRecyclerViewAdapter.java b/app/src/main/java/com/majinnaibu/monstercards/ui/library/MonsterListRecyclerViewAdapter.java similarity index 50% rename from app/src/main/java/com/majinnaibu/monstercards/ui/MonsterListRecyclerViewAdapter.java rename to app/src/main/java/com/majinnaibu/monstercards/ui/library/MonsterListRecyclerViewAdapter.java index e42ecef..1d853dd 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/ui/MonsterListRecyclerViewAdapter.java +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/library/MonsterListRecyclerViewAdapter.java @@ -1,4 +1,4 @@ -package com.majinnaibu.monstercards.ui; +package com.majinnaibu.monstercards.ui.library; import android.content.Context; import android.view.LayoutInflater; @@ -6,87 +6,67 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import androidx.navigation.NavDirections; -import androidx.navigation.Navigation; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.majinnaibu.monstercards.R; import com.majinnaibu.monstercards.models.Monster; -import com.majinnaibu.monstercards.ui.library.LibraryFragment; -import com.majinnaibu.monstercards.ui.library.LibraryFragmentDirections; import java.util.ArrayList; import java.util.List; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.schedulers.Schedulers; public class MonsterListRecyclerViewAdapter extends RecyclerView.Adapter { public interface ItemCallback { - void onItem(Monster monster); + void onItemCallback(Monster monster); } - // TODO: Replace SimpleItemRecyclerViewAdapter with something better like MonsterListRecyclerViewAdapter that can be reused in search - - private final LibraryFragment mParentActivity; private List mValues; - private final boolean mTwoPane; private final Context mContext; private final ItemCallback mOnDelete; + private final ItemCallback mOnClick; + private Disposable mDisposable; + private final Flowable> mItemsObservable; private final View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View view) { Monster monster = (Monster) view.getTag(); - // TODO: I would like to call navigateToMonsterDetail(item.id) here - if (mTwoPane) { - // TODO: Figure out how to navigate to a MonsterDetailFragment when in two pane view. -// Bundle arguments = new Bundle(); -// arguments.putString(ItemDetailFragment.ARG_ITEM_ID, monster.id.toString()); -// ItemDetailFragment fragment = new ItemDetailFragment(); -// fragment.setArguments(arguments); -// mParentActivity.getSupportFragmentManager().beginTransaction() -// .replace(R.id.item_detail_container, fragment) -// .commit(); - } else { - NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monster.id.toString()); - Navigation.findNavController(view).navigate(action); + if (mOnClick != null) { + mOnClick.onItemCallback(monster); } } }; - public MonsterListRecyclerViewAdapter(LibraryFragment parent, + public MonsterListRecyclerViewAdapter(Context context, Flowable> itemsObservable, - ItemCallback onDelete, - boolean twoPane) { + ItemCallback onClick, + ItemCallback onDelete) { + mItemsObservable = itemsObservable; mValues = new ArrayList<>(); - mParentActivity = parent; - mTwoPane = twoPane; - mContext = parent.getContext(); + mContext = context; mOnDelete = onDelete; - - itemsObservable - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(monsters -> { - mValues = monsters; - notifyDataSetChanged(); - }); + mOnClick = onClick; + mDisposable = null; } @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + @NonNull + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.monster_list_content, parent, false); return new ViewHolder(view); } @Override - public void onBindViewHolder(final ViewHolder holder, int position) { - holder.mIdView.setText(mValues.get(position).id.toString().substring(0, 6)); - holder.mContentView.setText(mValues.get(position).name); - - holder.itemView.setTag(mValues.get(position)); + public void onBindViewHolder(final @NonNull ViewHolder holder, int position) { + Monster monster = mValues.get(position); + holder.mIdView.setText(monster.id.toString().substring(0, 6)); + holder.mContentView.setText(monster.name); + holder.itemView.setTag(monster); holder.itemView.setOnClickListener(mOnClickListener); } @@ -99,7 +79,7 @@ public class MonsterListRecyclerViewAdapter extends RecyclerView.Adapter { + mValues = monsters; + notifyDataSetChanged(); + }); + } + + @Override + public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + mDisposable.dispose(); + } + public void deleteItem(int position) { if (mOnDelete != null) { Monster monster = mValues.get(position); - mOnDelete.onItem(monster); + mOnDelete.onItemCallback(monster); } } }