Мой код ListFragment
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
<?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>
Но это не обновляет ListView
. Даже после перезапуска приложения обновленные элементы не отображаются. Мой ItemAdapter
простираетсяBaseAdapter
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;
}
}
Кто-нибудь может помочь?
android
android-listview
notifydatasetchanged
кодировщик
источник
источник
adapter
ссылки, почему вы проверяете его на null на одну строку ниже?Ответы:
Посмотрите на свой
onResume
метод вItemFragment
:то, что вы только что обновили перед вызовом,
notifyDataSetChanged()
является не полем адаптера,private List<Item> items;
а идентично объявленным полем фрагмента. Адаптер по-прежнему хранит ссылку на список элементов, которые вы передали при создании адаптера (например, во фрагменте onCreate). Самый короткий (в смысле количества изменений), но не элегантный способ заставить ваш код вести себя так, как вы ожидаете, - это просто заменить строку:с участием
Более элегантное решение:
1) удалить элементы
private List<Item> items;
изItemFragment
- нам нужно сохранить ссылку на них только в адаптере2) измените onCreate на:
3) добавить метод в ItemAdapter:
4) измените свой onResume на:
источник
adapter.swapItems();
а адаптер сделаетdbHelper.getItems()
все. Но в любом случае спасибо за ответ :)notifyDataSetChanged()
?Вы назначаете перезагруженные элементы глобальным переменным items
onResume()
, но это не отразится наItemAdapter
классе, потому что у него есть собственная переменная экземпляра с именем «items».Для обновления
ListView
добавьте вItemAdapter
класс refresh (), который принимает данные списка, т.е. элементыобновить
onResume()
с помощью следующего кодаисточник
В onResume () измените эту строку
в
Проблема в том, что вы никогда не сообщаете своему адаптеру список новых элементов. Если вы не хотите передавать новый список вашему адаптеру (а кажется, что это не так), просто используйте
items.addAll
после вашегоclear()
. Это гарантирует, что вы изменяете тот же список, на который ссылается адаптер.источник
adapter.clear()
что не заставляет адаптер понимать, что представление должно обновляться, ноadapter.add()
илиadapter.addAll()
делает. Спасибо за ответ!items.addAll()
а не адаптер .addAll (). Единственное, что позволяет адаптеру реагировать на изменения, - это расширениеnotifyDataSetChanged
. Причина, по которой адаптер вообще видит изменения, -items
это тот же список, что и адаптер.Если адаптер уже настроен, повторная установка не приведет к обновлению списка. Вместо этого сначала проверьте, есть ли у listview адаптер, а затем вызовите соответствующий метод.
Я думаю, что создавать новый экземпляр адаптера при настройке представления списка - не очень хорошая идея. Вместо этого создайте объект.
Также вы можете попробовать запустить список обновления в потоке пользовательского интерфейса:
источник
ItemAdapter
том, что я хочу раскрасить строки, а в представлении списка отображается несколько элементов данных. Я разместил код адаптера.Если вы хотите обновить ваш ListView не имеет значения , если вы хотите сделать это на
onResume()
,onCreate()
или в какой - либо другой функции, первая вещь , которую вы должны понять, что вам не нужно будет создать новый экземпляр адаптера, просто Заселите снова массивы с вашими данными. Идея примерно такая:Поэтому в зависимости от этого ответа вы должны использовать то же самое
List<Item>
в своемFragment
. При первой инициализации адаптера вы заполняете список элементами и устанавливаете адаптер для просмотра списка. После этого при каждом изменении в ваших элементах вы должны очищать значения из основного,List<Item> items
а затем снова заполнять его своими новыми элементами и вызыватьnotifySetDataChanged();
.Вот как это работает :).
источник
Ответ AlexGo помог мне:
Обновление списка работало для меня раньше, когда обновление запускалось из события графического интерфейса пользователя, таким образом, находясь в потоке пользовательского интерфейса.
Однако, когда я обновляю список из другого события / потока, т. Е. Вызова извне приложения, обновления не будет в потоке пользовательского интерфейса, и он проигнорирует вызов getListView. Вызов обновления с помощью runOnUiThread, как указано выше, помог мне. Спасибо!!
источник
Попробуй это
источник
Попробуйте это в
onPause()
методе класса Activity.источник
должен сделать свое дело.
источник
Если ваш список содержится в самом адаптере, следует также вызвать функцию, обновляющую список
notifyDataSetChanged()
.Запуск этой функции из потока пользовательского интерфейса помог мне:
refresh()
Функции внутри адаптераЗатем, в свою очередь, запустите эту функцию из потока пользовательского интерфейса
источник
Попробуйте вот так:
вместо того:
Вы должны
notifyDataSetChanged()
вListView
не к классу адаптера.источник