Kode ListFragment saya
public class ItemFragment extends ListFragment {
private DatabaseHandler dbHelper;
private static final String TITLE = "Items";
private static final String LOG_TAG = "debugger";
private ItemAdapter adapter;
private List<Item> items;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.item_fragment_list, container, false);
return view;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
getActivity().setTitle(TITLE);
dbHelper = new DatabaseHandler(getActivity());
items = dbHelper.getItems();
adapter = new ItemAdapter(getActivity().getApplicationContext(), items);
this.setListAdapter(adapter);
}
@Override
public void onResume() {
super.onResume();
items.clear();
items = dbHelper.getItems(); //reload the items from database
adapter.notifyDataSetChanged();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if(dbHelper != null) { //item is edited
Item item = (Item) this.getListAdapter().getItem(position);
Intent intent = new Intent(getActivity(), AddItemActivity.class);
intent.putExtra(IntentConstants.ITEM, item);
startActivity(intent);
}
}
}
ListView saya
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Tapi ini tidak menyegarkan ListView
. Bahkan setelah memulai ulang aplikasi, item yang diperbarui tidak ditampilkan. Saya ItemAdapter
meluasBaseAdapter
public class ItemAdapter extends BaseAdapter{
private LayoutInflater inflater;
private List<Item> items;
private Context context;
public ProjectListItemAdapter(Context context, List<Item> items) {
super();
inflater = LayoutInflater.from(context);
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewHolder holder = null;
if(convertView == null) {
holder = new ItemViewHolder();
convertView = inflater.inflate(R.layout.list_item, parent,false);
holder.itemName = (TextView) convertView.findViewById(R.id.topText);
holder.itemLocation = (TextView) convertView.findViewById(R.id.bottomText);
convertView.setTag(holder);
} else {
holder = (ItemViewHolder) convertView.getTag();
}
holder.itemName.setText("Name: " + items.get(position).getName());
holder.itemLocation.setText("Location: " + items.get(position).getLocation());
if(position % 2 == 0) {
convertView.setBackgroundColor(context.getResources().getColor(R.color.evenRowColor));
} else {
convertView.setBackgroundColor(context.getResources().getColor(R.color.oddRowColor));
}
return convertView;
}
private static class ItemViewHolder {
TextView itemName;
TextView itemLocation;
}
}
Bisakah seseorang membantu?
android
android-listview
notifydatasetchanged
Pembuat kode
sumber
sumber
adapter
referensi mengapa Anda mengujinya untuk null satu baris di bawah ini?Jawaban:
Lihat
onResume
metode Anda diItemFragment
:apa yang baru saja Anda perbarui sebelum memanggil
notifyDataSetChanged()
bukanlah bidang adaptorprivate List<Item> items;
tetapi bidang fragmen yang dideklarasikan secara identik. Adaptor masih menyimpan referensi ke daftar item yang Anda teruskan saat Anda membuat adaptor (misalnya di onCreate fragmen). Cara terpendek (dalam arti jumlah perubahan) tetapi bukan cara elegan untuk membuat kode Anda berperilaku seperti yang Anda harapkan adalah dengan mengganti baris:dengan
Solusi yang lebih elegan:
1) hapus item
private List<Item> items;
dariItemFragment
- kita perlu menyimpan referensi ke item tersebut hanya di adaptor2) ubah onCreate menjadi:
3) tambahkan metode di ItemAdapter:
4) ubah onResume Anda menjadi:
sumber
adapter.swapItems();
dan adaptor akan melakukandbHelper.getItems()
hal itu. Tapi terima kasih atas jawabannya :)notifyDataSetChanged()
?Anda menugaskan item yang dimuat ulang ke item variabel global di
onResume()
, tetapi ini tidak akan terlihat diItemAdapter
kelas, karena memiliki variabel contoh sendiri yang disebut 'item'.Untuk menyegarkan
ListView
, tambahkan refresh () diItemAdapter
kelas yang menerima data daftar yaitu itemperbarui
onResume()
dengan kode berikutsumber
Di onResume () ubah baris ini
untuk
Masalahnya adalah Anda tidak pernah memberi tahu adaptor Anda tentang daftar item baru. Jika Anda tidak ingin meneruskan daftar baru ke adaptor Anda (sepertinya Anda tidak), maka gunakan saja
items.addAll
setelah Andaclear()
. Ini akan memastikan Anda memodifikasi daftar yang sama dengan referensi adaptor.sumber
adapter.clear()
tidak memaksa adaptor untuk menyadari bahwa tampilan harus di-refresh, tetapiadapter.add()
atauadapter.addAll()
tidak. Terima kasih atas jawabannya!items.addAll()
dan bukan adapter.addAll (). Satu-satunya hal yang membiarkan adaptor bereaksi terhadap perubahan adalahnotifyDataSetChanged
. Alasan adaptor melihat perubahan sama sekali adalahitems
daftar tersebut adalah daftar yang sama yang digunakan adaptor.Jika adaptor sudah disetel, menyetelnya lagi tidak akan menyegarkan tampilan daftar. Sebagai gantinya, periksa dulu apakah listview memiliki adaptor dan kemudian panggil metode yang sesuai.
Saya pikir itu bukan ide yang sangat baik untuk membuat contoh baru dari adaptor saat mengatur tampilan daftar. Sebagai gantinya, buatlah sebuah objek.
Anda juga dapat mencoba menjalankan daftar refresh di UI Thread:
sumber
ItemAdapter
adalah saya ingin mewarnai baris dan tampilan daftar menampilkan beberapa item data. Saya telah memposting kode untuk adaptor.Jika Anda ingin memperbarui tampilan daftar Anda tidak masalah jika Anda ingin melakukannya
onResume()
,onCreate()
atau di beberapa fungsi lain, hal pertama yang harus Anda sadari adalah bahwa Anda tidak perlu membuat contoh baru dari adaptor, cukup isi array dengan data Anda lagi. Idenya mirip dengan ini:Jadi tergantung pada jawaban itu, Anda harus menggunakan yang sama
List<Item>
diFragment
. Dalam inisialisasi adaptor pertama Anda, Anda mengisi daftar Anda dengan item dan mengatur adaptor ke listview Anda. Setelah itu di setiap perubahan pada item Anda, Anda harus menghapus nilai dari utamaList<Item> items
dan kemudian mengisinya lagi dengan item baru Anda dan memanggilnotifySetDataChanged();
.Begitulah cara kerjanya :).
sumber
Jawaban dari AlexGo berhasil untuk saya:
Pembaruan Daftar berfungsi untuk saya sebelumnya ketika pembaruan dipicu dari acara GUI, sehingga berada di utas UI.
Namun, ketika saya memperbarui daftar dari acara / utas lain - yaitu panggilan dari luar aplikasi, pembaruan tidak akan berada di utas UI dan mengabaikan panggilan ke getListView. Memanggil pembaruan dengan runOnUiThread seperti di atas melakukan trik bagi saya. Terima kasih!!
sumber
Coba ini
sumber
Coba ini dalam
onPause()
metode kelas Aktivitas.sumber
harus melakukan triknya.
sumber
Jika daftar Anda terdapat dalam Adaptor itu sendiri, memanggil fungsi yang memperbarui daftar juga harus memanggil
notifyDataSetChanged()
.Menjalankan fungsi ini dari UI Thread melakukan trik untuk saya:
The
refresh()
fungsi dalam AdapterKemudian secara bergiliran jalankan fungsi ini dari UI Thread
sumber
Coba seperti ini:
dari pada:
Anda harus
notifyDataSetChanged()
keListView
tidak ke kelas adaptor.sumber