Cara memperbarui / menyegarkan item tertentu di RecyclerView

112

Saya mencoba menyegarkan item tertentu di RecyclerView.

Cerita: Setiap kali pengguna mengklik item, itu terlihat AlertDialog. Pengguna dapat mengetik beberapa teks dengan mengklik tombol ok. Saya ingin menunjukkan teks ini di item ini dan menunjukkan tidak terlihat ImageView- dinyatakan dalam XML dan adaptor ViewHolder-

Saya menggunakan fungsi ini di AlertDialogTombol Positif untuk memperbarui item:

private void updateListItem(int position) {
  View view = layoutManager.findViewByPosition(position);
  ImageView medicineSelected = (ImageView) view.findViewById(R.id.medicine_selected);
  medicineSelected.setVisibility(View.VISIBLE);
  TextView orderQuantity = (TextView) view.findViewById(R.id.order_quantity);
  orderQuantity.setVisibility(View.VISIBLE);
  orderQuantity.setText(quantity + " packet added!");

  medicinesArrayAdapter.notifyItemChanged(position);
}

Tetapi kode ini tidak hanya mengubah itemView pada posisi yang diteruskan, tetapi juga mengubah beberapa itemView lainnya!

Bagaimana cara mengubah itemView tertentu dengan benar dengan mengkliknya?

Elgendy
sumber

Jawaban:

98

Anda bisa menggunakan notifyItemChanged(int position)metode dari kelas RecyclerView.Adapter. Dari dokumentasi:

Beritahu pengamat yang terdaftar bahwa item pada posisinya telah berubah. Setara dengan memanggil notifyItemChanged (position, null) ;.

Ini adalah acara perubahan item, bukan acara perubahan struktural. Ini menunjukkan bahwa setiap refleksi data pada posisi sudah kadaluwarsa dan harus diperbarui. Item di posisi mempertahankan identitas yang sama.

Karena Anda sudah memiliki posisi tersebut, itu akan bekerja untuk Anda.

Edson Menegatti
sumber
9
Saya sudah menggunakannya tetapi jika saya ingin memperbarui posisi 0, itu memperbarui posisi 0, 9, 19, ...
Elgendy
Maaf, tidak mengerti komentar anda Posisi mana yang sedang diperbarui? 0, 9 atau kisaran antara 0 dan 9?
Edson Menegatti
Tidak, ini tidak berkisar, setiap kali saya memperbarui item, itu juga menyegarkan item yang tidak diinginkan
Elgendy
@Pelajar Saat Anda memperbarui ViewHolder di posisi 0, ViewHolder tetap diperbarui. RecyclerView akan mendaur ulang ViewHolder itu dan menggunakannya untuk posisi 9, jadi Anda melihat perubahan itu di sana. Saya merekomendasikan pengaturan teks ini di onBindViewHolder () sebagai gantinya - dengan cara itu, setiap kali ViewHolder didaur ulang, Anda dapat memeriksa posisinya dan mengatur teks atau membuat gambar terlihat atau apa pun dengan benar.
Cliabhach
@Cliabhach masih masalah yang sama melakukan perubahan dionBindViewHolder()
Choletski
39

Perbarui satu item

  1. Perbarui item data
  2. Beri tahu adaptor perubahan dengan notifyItemChanged(updateIndex)

Contoh

Ubah item "Domba" sehingga bertuliskan "Saya suka domba".

Perbarui satu item

String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);

Jawaban lengkap saya dengan lebih banyak contoh ada di sini .

Suragch
sumber
bagaimana melakukannya jika saya ingin data yang diperbarui beralih ke atas
Choy
@ Choy, setelah Anda memperbarui data, Anda dapat memindahkannya ke indeks 0. Lihat bagian Memindahkan Item Tunggal dari item ini
Suragch
11

Tambahkan teks yang diubah ke daftar data model Anda

mdata.get(position).setSuborderStatusId("5");
mdata.get(position).setSuborderStatus("cancelled");
notifyItemChanged(position);
Shamir Kp
sumber
10

Saya pikir saya punya Ide tentang bagaimana menangani ini. Memperbarui sama dengan menghapus dan mengganti pada posisi yang tepat. Jadi saya pertama-tama menghapus item dari posisi itu menggunakan kode di bawah ini:

public void removeItem(int position){
    mData.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, mData.size());
}

dan kemudian saya akan menambahkan item pada posisi tertentu seperti yang ditunjukkan di bawah ini:

public void addItem(int position, Landscape landscape){
    mData.add(position, landscape);
    notifyItemInserted(position);
    notifyItemRangeChanged(position, mData.size());
}

Saya mencoba menerapkan ini sekarang. Saya akan memberi Anda umpan balik saat saya selesai!

EGBENCHONG II J. Ayuk
sumber
2
Anda melakukan satu langkah ekstra. Cukup ganti elemen di posisi dan panggil item notifyItemChanged (position);
toshkinl
@toshkinl Bagaimana Anda tahu jika data berasal dari JSONObject? tanpa posisi?
olajide
7

Saya harus menyelesaikan masalah ini dengan menangkap posisi item yang perlu dimodifikasi dan kemudian di panggilan adaptor

public void refreshBlockOverlay(int position) {
    notifyItemChanged(position);
}

, ini akan memanggil onBindViewHolder (pemegang ViewHolder, posisi int) untuk item khusus ini di posisi khusus ini.

haneenCo
sumber
2

Solusi di bawah ini berhasil untuk saya:

Pada item RecyclerView, pengguna akan mengklik tombol tetapi tampilan lain seperti TextView akan diperbarui tanpa langsung memberi tahu adaptor:

Saya menemukan solusi yang baik untuk ini tanpa menggunakan metode notifyDataSetChanged (), metode ini memuat ulang semua data recyclerView jadi jika Anda memiliki gambar atau video di dalam item maka mereka akan memuat ulang dan pengalaman pengguna tidak akan baik:

Berikut adalah contoh klik pada ikon mirip ImageView dan hanya memperbarui satu TextView (Mungkin untuk memperbarui lebih banyak tampilan dengan cara yang sama dari item yang sama) untuk menunjukkan seperti pembaruan hitungan setelah menambahkan +1:

// View holder class inside adapter class
public class MyViewHolder extends RecyclerView.ViewHolder{

    ImageView imageViewLike;

    public MyViewHolder(View itemView) {
         super(itemView);

        imageViewLike = itemView.findViewById(R.id.imageViewLike);
        imageViewLike.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = getAdapterPosition(); // Get clicked item position
                TextView tv = v.getRootView().findViewById(R.id.textViewLikeCount); // Find textView of recyclerView item
                resultList.get(pos).setLike(resultList.get(pos).getLike() + 1); // Need to change data list to show updated data again after scrolling
                tv.setText(String.valueOf(resultList.get(pos).getLike())); // Set data to TextView from updated list
            }
        });
    }
Touhid
sumber
1

Sebuah cara yang berhasil untuk saya pribadi, menggunakan metode adaptor recyclerview untuk menangani perubahan pada itemnya.

Ini akan berjalan dengan cara yang mirip dengan ini, buat metode dalam tampilan pendaur ulang kustom Anda seperti ini:

public void modifyItem(final int position, final Model model) {
    mainModel.set(position, model);
    notifyItemChanged(position);
}
pengguna3709410
sumber
0

Di kelas adaptor Anda, dalam metode onBindViewHolder, setel ViewHolder ke setIsRecyclable (false) seperti pada kode di bawah ini.

@Override
public void onBindViewHolder(RecyclerViewAdapter.ViewHolder p1, int p2)
{
    // TODO: Implement this method
    p1.setIsRecyclable(false);

    // Then your other codes
}
shankar_vl
sumber
0

Anda hanya perlu menambahkan kode berikut di kotak dialog peringatan saat klik simpan

          recyclerData.add(position, updateText.getText().toString());
          recyclerAdapter.notifyItemChanged(position);
Dhruvisha
sumber
0

Masalahnya adalah RecyclerView.Adatpertidak menyediakan metode apa pun yang mengembalikan indeks elemen

public abstract static class Adapter<VH extends ViewHolder> {
  /**
   * returns index of the given element in adapter, return -1 if not exist
   */
  public int indexOf(Object elem);
}

Solusi saya adalah membuat contoh peta untuk (elemen, posisi) s

public class FriendAdapter extends RecyclerView.Adapter<MyViewHolder> {
  private Map<Friend, Integer> posMap ;
  private List<Friend> friends;

  public FriendAdapter(List<Friend> friends ) {
    this.friends = new ArrayList<>(friends);
    this.posMap = new HashMap<>();
    for(int i = 0; i < this.friends.size(); i++) {
      posMap.put(this.friends.get(i), i);
    }
  }

  public int indexOf(Friend friend) {
    Integer position = this.posMap.get(elem);
    return position == null ? -1 : position;
  }
  // skip other methods in class Adapter
}
  • jenis elemen (di sini kelas Friend) harus diimplementasikan hashCode()dan equals()karena itu adalah kunci dalam hashmap.

ketika sebuah elemen berubah,

  void someMethod() {
    Friend friend = ...;
    friend.setPhoneNumber('xxxxx');

    int position = friendAdapter.indexOf(friend);
    friendAdapter.notifyItemChanged(position);

  }

Ini bagus untuk mendefinisikan metode pembantu

public class FriendAdapter extends extends RecyclerView.Adapter<MyViewHolder> {

  public void friendUpdated(Friend friend) {
    int position = this.indexOf(friend);
    this.notifyItemChanged(position);
  }
}

Contoh peta (Map<Friend, Integer> posMap ) tidak selalu diperlukan. Jika map tidak digunakan, perulangan di seluruh daftar dapat menemukan posisi sebuah elemen.

chmin
sumber
-1

Itu juga masalah terakhir saya. Di sini solusi saya, saya menggunakan Model data dan adaptor untuk RecyclerView saya

 /*Firstly, register your new data to your model*/
 DataModel detail = new DataModel(id, name, sat, image);

 /*after that, use set to replace old value with the new one*/
 int index = 4;
 mData.set(index, detail);

 /*finally, refresh your adapter*/
 if(adapter!=null)
    adapter.notifyItemChanged(index);
deya tri
sumber
-1

jika Anda membuat satu objek dan menambahkannya ke daftar yang Anda gunakan di adaptor Anda, ketika Anda mengubah satu elemen daftar Anda di adaptor semua item Anda yang lain juga berubah dengan kata lain semua tentang referensi dan daftar Anda tidak pegang salinan terpisah dari objek tunggal itu.

A. sobhdel
sumber
-5

Dalam adaptor RecyclerView, Anda harus memiliki ArrayList dan juga satu metode addItemsToList(items)untuk menambahkan item daftar ke ArrayList. Kemudian Anda dapat menambahkan item daftar dengan memanggil adapter.addItemsToList(items)secara dinamis. Setelah semua item daftar Anda ditambahkan ke ArrayList maka Anda dapat memanggil adapter.notifyDataSetChanged()untuk menampilkan daftar Anda.

Anda bisa menggunakan notifyDataSetChangeddi adaptor untuk RecyclerView

Nooruddin Lakhani
sumber
ya saya punya ArrayList untuk data, ini berfungsi tanpa masalah, masalah saya dalam memperbarui item-yang ada- tertentu dalam daftar ini
Elgendy
Anda harus memiliki posisi item yang sedang diperbarui kemudian Anda hanya perlu meletakkan item baru di posisinya masing-masing seperti mList.add (position) .setName ("nama baru"); lalu gunakan mAdapter.notifyDataSetChanged ();
Nooruddin Lakhani
4
Jawaban ini mengabaikan keinginan untuk memperbarui satu item. Memanggil notifyDataSetChanged () hanya boleh dilakukan ketika seluruh kumpulan data berubah.
Mark McClelland