Попытка проверить Room DB с помощью адаптера RecyclerView - PullRequest
0 голосов
/ 06 июня 2019

Я пытаюсь вставить, удалить и проверить мою комнатную БД из адаптера RecyclerView, но я не могу сделать это правильно, потому что это как адаптер, постоянно сбрасывающий элементы.

Основная функциональность, которую я ищу, - добавить элемент непосредственно из адаптера RecyclerView в БД.

Несмотря на то, что я вставляю и удаляю данные в БД, я не могу сохранять или проверять состояние своей кнопки переключения в зависимости от наличия каждого элемента в БД.

enter image description here enter image description here

PS не возражаю против всей этой регистрации ...

Вот мой адаптер

public class MovieListRvAdapter extends RecyclerView.Adapter<MovieListRvAdapter.MoviesViewHolder>  {
private Context mContext;
private List<Movie> mMovies;
private static RvClickListener listener;
private boolean isInFavsAlready;
private static String LOG_TAG = MovieListRvAdapter.class.getSimpleName();

public interface RvClickListener{
     void rvClickListener(View v, int position);
}

public void swapData(List<Movie> movies)
{
    if(movies == null || movies.size()==0)
        return;
    if (mMovies != null && mMovies.size()>0)
        mMovies.clear();
    mMovies.addAll(movies);
    notifyDataSetChanged();
}

public MovieListRvAdapter(Context c, List<Movie> myMovieData, RvClickListener listener) {
    this.mContext = c;
    this.mMovies =myMovieData;
    this.listener = listener;

}

@NonNull
@Override
public MovieListRvAdapter.MoviesViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
    Context context = viewGroup.getContext();
    int layoutIdForListItem = R.layout.movie_list_item;
    LayoutInflater inflater = LayoutInflater.from(context);
    boolean shouldAttachToParentImmediately = false;
    View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
    MoviesViewHolder viewHolder = new MoviesViewHolder(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(@NonNull MovieListRvAdapter.MoviesViewHolder holder, int position) {
    Movie movie = this.mMovies.get(position);
    Picasso.get()
            .load(movie.getPoster_path())
            .placeholder(R.drawable.ic_launcher_background)
            .error(R.drawable.ic_launcher_foreground)
            .into(holder.moviePosterIv);
    holder.movieTitleTv.setText(movie.getTitle());
    holder.ratingBar.setRating(Float.valueOf(movie.getVote_average())/2);
    holder.movieReleaseDateTv.setText(modifyDateLayout(movie.getRelease_date()));
     boolean bool =isMovieInFavorites(movie);
    Log.d(LOG_TAG, "isMovieInFavorites " +bool + " " +movie.getTitle());
    if(bool){
        holder.favButton.setChecked(true);

    }else{
        holder.favButton.setChecked(false);
    }
}

@Override
public int getItemCount() {
     return (null != mMovies ? mMovies.size() : 0);
}

/**
 * Cache of the children views for a list item.
 */
public class MoviesViewHolder extends RecyclerView.ViewHolder
        implements View.OnClickListener {
    ImageView moviePosterIv;
    TextView movieTitleTv;
    RatingBar ratingBar;
    TextView movieReleaseDateTv;
    ToggleButton favButton;

    public MoviesViewHolder(View itemView) {
        super(itemView);
        ratingBar = itemView.findViewById(R.id.rating);
        moviePosterIv = itemView.findViewById(R.id.poster_path);
        movieTitleTv = itemView.findViewById(R.id.movieTitleListItem);
        movieReleaseDateTv = itemView.findViewById(R.id.movieReleaseDate);
        favButton = itemView.findViewById(R.id.toggleButton);
        favButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                int position = getLayoutPosition();
                final Movie movie = mMovies.get(position);
                if (isChecked && !isMovieInFavorites(movie)){
                final AppDatabase mDb = AppDatabase.getInstance(mContext);
                    Log.d(LOG_TAG, "isMovieInFavorites " +isMovieInFavorites(movie));
                AppExecutors.getInstance().diskIO().execute(new Runnable() {
                    @Override
                    public void run() {
                        mDb.movieDao().insertMovie(movie);
                        Log.d(LOG_TAG, " " + movie);
                    }
                });
                    favButton.setChecked(true);
                }
                else if (!isChecked){
                    final AppDatabase mDb = AppDatabase.getInstance(mContext);
                    AppExecutors.getInstance().diskIO().execute(new Runnable() {
                        @Override
                        public void run() {
                            mDb.movieDao().deleteMovie(movie);
                            Log.d(LOG_TAG, "movie deleted " + movie);
                        }
                    });
                    favButton.setChecked(false);
                }
            }
        });
        itemView.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        Context context = v.getContext();
        int clickedPosition = getAdapterPosition();
        Intent i = new Intent(context, MovieDetailsActivity.class);
        Movie movie = mMovies.get(clickedPosition);
        i.putExtra(MovieDetailsActivity.EXTRA_MOVIE, movie);
        context.startActivity(i);
        listener.rvClickListener(v, clickedPosition);
    }
}

public boolean isMovieInFavorites(Movie movie) {
    final AppDatabase mDb = AppDatabase.getInstance(mContext);
    AppExecutors.getInstance().diskIO().execute(new Runnable() {
        @Override
        public void run() {
            int dbMovieID = mDb.movieDao().searchFavsByMovieID(movie.getId());
            Log.d(LOG_TAG, "result of " + dbMovieID + " " + movie.getTitle());
            if(dbMovieID !=0){
                isInFavsAlready = true;

            }else{
                isInFavsAlready= false;
            }
        }
    });

//Log.d (LOG_TAG, "результат метода1" + isInFavsAlready + "" + movie.getTitle ());return isInFavsAlready;}

@Dao
public interface MovieDao {

@Query("SELECT * FROM moviesTable ORDER BY id")
LiveData<List<Movie>> loadAllMovies();

@Query("SELECT * FROM moviesTable WHERE id = :id")
LiveData<Movie> loadMovieById(int id);

@Query("SELECT id FROM moviesTable WHERE id = :id")
int searchFavsByMovieID(int id);

@Query("SELECT id FROM moviesTable WHERE id = :id")
LiveData<Integer> searchFavsByMovieIDLive(int id);

@Insert
void insertMovie(Movie movie);

@Query("DELETE FROM moviesTable WHERE movieId = :movieID")
void deleteByID(int movieID);

@Delete
void deleteMovie(Movie movie);

}

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Проблема здесь в вашей функции isMovieInFavorites.Этот оператор возврата return isInFavsAlready; запускается до того, как Room заканчивает свой запрос (ваш запрос выполняется в потоке ввода-вывода).Итак, что вы можете сделать здесь, это дождаться завершения запроса, прежде чем обновлять ваш пользовательский интерфейс

public void isMovieInFavorites(Movie movie) {
    final AppDatabase mDb = AppDatabase.getInstance(mContext);
    AppExecutors.getInstance().diskIO().execute(new Runnable() {
        @Override
        public void run() {
            int dbMovieID = mDb.movieDao().searchFavsByMovieID(movie.getId());
            Log.d(LOG_TAG, "result of " + dbMovieID + " " + movie.getTitle());
            if(dbMovieID !=0){
                isInFavsAlready = true;
                mContext.runOnUiThread(() -> {
                    holder.favButton.setChecked(true);
                }
            }else{
                isInFavsAlready= false;
                mContext.runOnUiThread(() -> {
                    holder.favButton.setChecked(false);
                }
            }

        }
    });
}
0 голосов
/ 06 июня 2019

Полагаю, это проблема LiveData.Я делал этот проект более года назад, до того, как появилась LiveData.В прошлые выходные я обновился, чтобы использовать Room и LiveData.Я столкнулся с этой же проблемой. Вот коммит , где было сделано исправление.Я храню все фильмы в БД и у меня есть столбец, в котором хранится, является ли он любимым.К сожалению, я провел довольно много рефакторинга в этом коммите, но я думаю, что соответствующая часть здесь (игнорируйте ужасное имя метода, потому что мои сетевые вызовы - беспорядок):

public boolean isFavoriteAlreadyInBackground(int movieId) {
    //  old code
    //    LiveData<Movie> movie = movieDao.getMovie(movieId);
    //    return movie.getValue() != null && movie.getValue().getFavorite();
        //new code
        Movie movie = movieDao.getMovie(movieId);
        return movie != null && movie.getFavorite();
    }

Когда я проверялLiveData Movie возвращало значение isFavorite в значение false, поэтому я начал проверять версию данных db, не являющуюся живым, и она имела правильное значение.Я уверен, что мой проект выглядит несколько иначе, чем ваш, но не стесняйтесь просматривать его и заимствовать любые части, которые будут работать для вас, хотя это в значительной степени работа в процессе.Надеюсь, это поможет.

...