Meu código 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);
}
}
}
My 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>
Mas isso não atualiza o ListView
. Mesmo depois de reiniciar o aplicativo, os itens atualizados não são exibidos. Meu ItemAdapter
estendeBaseAdapter
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;
}
}
Alguém pode ajudar por favor?
adapter
referência, por que testá-lo para null uma linha abaixo?Respostas:
Observe o seu
onResume
método emItemFragment
:o que você acabou de atualizar antes de chamar
notifyDataSetChanged()
não é o campo do adaptador,private List<Item> items;
mas o campo declarado de forma idêntica do fragmento. O adaptador ainda armazena uma referência à lista de itens que você passou quando criou o adaptador (por exemplo, no fragmento onCreate). A maneira mais curta (em termos de número de mudanças), mas não elegante, de fazer seu código se comportar como você espera é simplesmente substituir a linha:com
Uma solução mais elegante:
1) remover itens
private List<Item> items;
deItemFragment
- precisamos manter referência a eles apenas no adaptador2) alterar onCreate para:
3) adicionar método no ItemAdapter:
4) mude seu onResume para:
fonte
adapter.swapItems();
e o adaptador faria asdbHelper.getItems()
coisas. De qualquer forma, obrigado pela resposta :)notifyDataSetChanged()
?Você está atribuindo itens recarregados a itens de variáveis globais em
onResume()
, mas isso não se refletirá naItemAdapter
classe, porque ela tem sua própria variável de instância chamada 'itens'.Para atualizar
ListView
, adicione um refresh () naItemAdapter
classe que aceita dados de lista, ou seja, itensatualizar
onResume()
com o seguinte códigofonte
Em onResume () altere esta linha
para
O problema é que você nunca informa ao adaptador sobre a nova lista de itens. Se você não quiser passar uma nova lista para o seu adaptador (parece que não), use
items.addAll
depois do seuclear()
. Isso garantirá que você esteja modificando a mesma lista à qual o adaptador faz referência.fonte
adapter.clear()
não força o adaptador a perceber que a visualização deve ser atualizada, masadapter.add()
ouadapter.addAll()
faz. Obrigado pela resposta!items.addAll()
e não adapter.addAll (). A única coisa que permite que o adaptador reaja às mudanças é onotifyDataSetChanged
. O motivo pelo qual o adaptador vê as alterações é que aitems
lista é a mesma que o adaptador está usando.Se o adaptador já estiver definido, configurá-lo novamente não atualizará a visualização da lista. Em vez disso, verifique primeiro se o listview tem um adaptador e, em seguida, chame o método apropriado.
Acho que não é uma ideia muito boa criar uma nova instância do adaptador enquanto define a exibição de lista. Em vez disso, crie um objeto.
Além disso, você pode tentar executar a lista de atualização no UI Thread:
fonte
ItemAdapter
é que eu quero colorir as linhas e a exibição de lista exibe vários itens de dados. Publiquei o código do adaptador.Se você deseja atualizar sua visualização de lista, não importa se deseja fazer isso em
onResume()
,onCreate()
ou em alguma outra função, a primeira coisa que você deve perceber é que você não precisará criar uma nova instância do adaptador, apenas preencher os arrays com seus dados novamente. A ideia é algo semelhante a esta:Portanto, dependendo dessa resposta, você deve usar a mesma
List<Item>
na suaFragment
. Em sua primeira inicialização do adaptador, você preenche sua lista com os itens e define o adaptador para seu listview. Depois disso, em cada mudança em seus itens, você deve limpar os valores do principalList<Item> items
e então preenchê-los novamente com seus novos itens e chamarnotifySetDataChanged();
.É assim que funciona : ).
fonte
Uma resposta do AlexGo funcionou para mim:
A atualização de lista funcionou para mim antes, quando a atualização foi disparada a partir de um evento da GUI, estando, portanto, no thread de interface do usuário.
No entanto, quando eu atualizo a lista de outro evento / thread - ou seja, uma chamada de fora do aplicativo, a atualização não estaria no thread de IU e ele ignorou a chamada para getListView. Chamar a atualização com runOnUiThread como acima funcionou para mim. Obrigado!!
fonte
Tente isto
fonte
Tente isso no
onPause()
método da classe Activity.fonte
deve fazer o truque.
fonte
Se sua lista estiver contida no próprio conector, chamar a função que atualiza a lista também deve ser chamada
notifyDataSetChanged()
.Executar esta função a partir do UI Thread funcionou para mim:
A
refresh()
função dentro do adaptadorEntão, por sua vez, execute esta função a partir do UI Thread
fonte
Tente assim:
ao invés de:
Você tem que
notifyDataSetChanged()
fazer oListView
não para a classe do adaptador.fonte