Android RecyclerView не обновляется после вставки - PullRequest
0 голосов
/ 05 января 2019

У меня проблема с моим RecyclerView.

У меня есть ProductDetailActivity, который показывает детали продукта, и у меня есть RecyclerView с его адаптером.

Пользователь может нажать на кнопку «Оценить», которая переходит к RatingActivity, где вы можете дать оценку продукту.

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

Вот мой код:

ProductDetailActivity:

public class ProductDetailActivity extends AppCompatActivity {

public AppDatabase appDatabase;
private static final String DATABASE_NAME = "Database_Shop";
private RecyclerView mRecycleviewRating;
private RatingAdapter mAdapterRating;
private Button btnGoToRatingActivity;
List<Rating> ratings;
Product p;
int id;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_product_detail);

    appDatabase = Room.databaseBuilder(getApplicationContext(),AppDatabase.class,DATABASE_NAME)
            .allowMainThreadQueries()
            .fallbackToDestructiveMigration()
            .build();

    btnGoToRatingActivity = findViewById(R.id.btn_goToRatingActivity);

    Intent intent = getIntent();

    id = intent.getIntExtra("productid", -1);

    // pour montrer tous les ratings d'un produit, tu fais un getall

    p = appDatabase.productDAO().getProductById(id);

    ImageView imageView = findViewById(R.id.imageDetail);
    TextView textViewName = findViewById(R.id.txt_nameDetail);
    TextView textViewAuthor = findViewById(R.id.txt_authorDetail);
    TextView textViewCategory = findViewById(R.id.txt_categoryDetail);
    TextView textViewDetail = findViewById(R.id.txt_descriptionDetail);


    Picasso.get().load(p.getProductImage()).fit().centerInside().into(imageView);
    textViewName.setText(p.getProductName());
    textViewAuthor.setText(p.getProductAuthor());
    textViewCategory.setText(p.getProductCategory());
    textViewDetail.setText(p.getProductDescription());


    ratings = appDatabase.ratingDAO().getRatingByProductId(id);

    mRecycleviewRating = findViewById(R.id.recyclerRating_view);

    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecycleviewRating.setLayoutManager(linearLayoutManager);

    //recyclerView.setLayoutManager(new LinearLayoutManager(this));
    mAdapterRating = new RatingAdapter(ratings);



    mRecycleviewRating.setAdapter(mAdapterRating);

    btnGoToRatingActivity.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Intent i = new Intent(ProductDetailActivity.this, RatingActivity.class);
            i.putExtra("productid", p.getProduct_id());
            startActivity(i);

        }
    });

    mAdapterRating.notifyDataSetChanged();

}


@Override
public void onResume() {
    super.onResume();
    ratings = appDatabase.ratingDAO().getRatingByProductId(id); // reload the items from database
    mAdapterRating.notifyDataSetChanged();
    System.out.println(mAdapterRating.ratings.size());
   }
}

RatingActivity:

public class RatingActivity extends AppCompatActivity implements RatingGiveFragment.RatingListener {

RelativeLayout mRelativeLayout;
private Button btnConfirmRating;
private EditText mComment;
private RatingBar mRatingBar;
public AppDatabase appDatabase;
private RatingAdapter mAdapter;
List<Rating> ratings;
private static final String DATABASE_NAME = "Database_Shop";

Product p;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rating);

    appDatabase = Room.databaseBuilder(getApplicationContext(),AppDatabase.class,DATABASE_NAME)
            .allowMainThreadQueries()
            .fallbackToDestructiveMigration()
            .build();



    int idProduct = RatingActivity.this.getIntent().getIntExtra("productid",-1);

    p = appDatabase.productDAO().getProductById(idProduct);

    mRatingBar = findViewById(R.id.rating_bar);

    mComment = findViewById(R.id.txt_insertOpinionText);

    mRelativeLayout = findViewById(R.id.activity_rating);

    btnConfirmRating = findViewById(R.id.buttonConfirmRating);

    mAdapter = new RatingAdapter(ratings);

    btnConfirmRating.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(!checkEmptyFields()) {
                Rating rating =  new Rating(p.getProduct_id(),UserConnected.connectedUser.getUser_id(),mRatingBar.getRating(), UserConnected.connectedUser.getUsername(), mComment.getText().toString());
                appDatabase.ratingDAO().insertRating(rating);
                mAdapter.notifyDataSetChanged();
                finish();
            }else{
                Toast.makeText(RatingActivity.this, "Empty Fields", Toast.LENGTH_SHORT).show();
            }
        }
    });

}



/*private class insertRating extends AsyncTask<String,Integer, Integer>
{
    @Override
    protected Integer doInBackground(String... strings) {
        Rating rating =  new Rating(Integer.parseInt(strings[0]), Integer.parseInt(strings[1]), Integer.parseInt(strings[2]), strings[3], strings[4]);
        appDatabase.ratingDAO().insertRating(rating);
        return 1;
    }

    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);
        if (integer == 1)
        {
            Toast.makeText(getApplicationContext(), getString(R.string.createRating), Toast.LENGTH_SHORT).show();

        }
    }

}*/


@Override
public void ratingChanged(int newRating) {
    RatingTextFragment textFragment = (RatingTextFragment) getSupportFragmentManager().findFragmentById(R.id.fmt_text);
    textFragment.setRating(newRating);
}

private boolean checkEmptyFields(){
    if(TextUtils.isEmpty(mComment.getText().toString())){
        return true;
    }else{
        return false;
    }
  }

 }

RatingAdapter:

public class RatingAdapter extends RecyclerView.Adapter<RatingAdapter.RatingViewHolder> {

List<Rating> ratings;

public RatingAdapter(List<Rating> ratings){
    this.ratings = ratings;
}


@NonNull
@Override
public RatingViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rating_row,viewGroup, false);
    return new RatingViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull RatingViewHolder ratingViewHolder, int position) {

    ratingViewHolder.ratingUsername.setText(ratings.get(position).getRatingUsername());
    ratingViewHolder.ratingNumber.setText(String.valueOf(ratings.get(position).getRatingNumber()) + "/5");
    ratingViewHolder.ratingComment.setText(ratings.get(position).getRatingText());

}

@Override
public int getItemCount() {
    return ratings.size();
}

public static class RatingViewHolder extends RecyclerView.ViewHolder{

    public TextView ratingUsername;
    public TextView ratingNumber;
    public TextView ratingComment;


    public RatingViewHolder(@NonNull View itemView) {
        super(itemView);
        ratingUsername = itemView.findViewById(R.id.txt_usernamerating);
        ratingNumber = itemView.findViewById(R.id.num_rating);
        ratingComment = itemView.findViewById(R.id.txt_ratingComment);
      }
   }
 }

Изображения: enter image description here

1 Ответ

0 голосов
/ 05 января 2019

Вы не получаете обновления в ProductDetailActivity, потому что вы не обновляете объект данных ratings в ProductDetailActivity, который является основой для RatingAdapter.

Было бы лучше использовать startActivityForResult в методе onClick() из ProductDetailActivity. Затем вам нужно переопределить метод onActivityResult() в ProductDetailActivity. Оцените возвращаемые значения и, при необходимости, обновите источник данных, затем вызовите notifyDataSetChanged

Это просто псевдокод!

Меняется на ProductDetailActivity:

    btnGoToRatingActivity.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent i = new Intent(ProductDetailActivity.this, RatingActivity.class);
            i.putExtra("productid", p.getProduct_id());     
            // with this you are telling the activity to expect results and..
            //..to deal with them in onActivityResult        
            startActivityForResult(i, 1);
        }
    });

        // You do not need this next line because setting the adaper triggers the first 
        //mAdapterRating.notifyDataSetChanged();
}

Добавьте метод onActivityResult() к ProductDetailActivity.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1) {
        if(resultCode == Activity.RESULT_OK){
            // trigger a method to update the data object that is linked to the adapter
            ratings = appDatabase.ratingDAO().getRatingByProductId(id);
            // and now that the data has actually been updated you can call notifyDataSetChanged!!
            mAdapterRating.notifyDataSetChanged();
        }
        if (resultCode == Activity.RESULT_CANCELED) {
            //Probably do nothing or make a Toast "Canceled"??
        }
    }
}

Меняется на RatingActivity:

btnConfirmRating.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(!checkEmptyFields()) {
            // I will just assume this works!
            Rating rating =  new Rating(p.getProduct_id(),UserConnected.connectedUser.getUser_id(),mRatingBar.getRating(), UserConnected.connectedUser.getUsername(), mComment.getText().toString());
            appDatabase.ratingDAO().insertRating(rating);
            Intent intent = new Intent();
            //If you need to return some value.. do it here other you do not need it
            //intent.putExtra("result", result);
            setResult(Activity.RESULT_OK, intent);
            finish();
        }else{
            Toast.makeText(RatingActivity.this, "Empty Fields", Toast.LENGTH_SHORT).show();
        }
    }
});

Обратите внимание, в RatingActivity, что в btnConfirmRating.setOnClickListener уведомление адаптера с помощью mAdapter.notifyDataSetChanged(); ничего не делает: во-первых, потому что адаптер в RatingActivity не имеет ничего общего с адаптером в ProductDetailActivity; во-вторых: вы звоните finish(); в следующей строке кода.

...