我有Adapter
名为AdapterActions
的{{1}}扩展名ArrayAdapter<Action>
。我向ArrayList<Action>
提供AdapterActions
,并使用该ArrayList填充ListView
。问题是:
我们假设这是我的ArrayList:
ListaActions(0) = a
ListaActions(1) = b
ListaActions(2) = c
ListaActions(3) = d
ListaActions(4) = e
我做ListaActions.remove(2)
然后我清除并重新添加每个Action
对象到ListaActions
,它成功地从ArrayList中删除了第三个对象,但是在ListView中它删除了最后一项(在这种情况下它将是ListaActions(4)的视图)并且它将在该ListView上表示的已删除对象(ListaActions(4))的每个属性设置为其默认值,即:int properties to 0,boolean properties真的......
当我关闭应用程序然后再次打开它时,它仍然是相同的,它不会“刷新”ListView。有什么想法吗?
我已经阅读了一些关于notifyDataSetChanged()
的帖子,但我不认为它可以工作,如果它的作用是“通知数据集已更改”,如果我重新启动应用程序时重建所有内容并且那些“空”视图仍然存在,并且ArrayList中的最后一个对象没有在listview中表示。
这是AdapterActions
:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
/*@SuppressLint("ViewHolder") */public class AdapterActions extends ArrayAdapter<Action>{
// our ViewHolder.
// caches our TextView
static class ViewHolderItem {
TextView codigo;
TextView accion;
TextView evento;
Switch UnSwitch;
boolean isChecked1;
}
Activity context;
ArrayList<Action> listaActions;
@SuppressLint("UseSparseArrays") Map <Integer, Boolean> map = new HashMap<Integer, Boolean>();
// Le pasamos al constructor el contexto y la lista de contactos
public AdapterActions(Activity context, ArrayList<Action> listaActions) {
super(context, R.layout.layout_adapter_actions, listaActions);
this.context = context;
this.listaActions = listaActions;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
// Rescatamos cada item del listview y lo inflamos con nuestro layout
//View item = convertView;
//item = context.getLayoutInflater().inflate(R.layout.layout_adapter_actions, null);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.layout_adapter_actions, parent, false);
// well set up the ViewHolder
viewHolder.codigo = (TextView) convertView.findViewById(R.id.codigo);
viewHolder.accion = (TextView) convertView.findViewById(R.id.accion);
viewHolder.evento = (TextView) convertView.findViewById(R.id.evento);
viewHolder.UnSwitch = (Switch) convertView.findViewById(R.id.activa);
convertView.setLongClickable(true);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
Action a = new Action(0, 1, 1, true);
AccionDefinida LaAccion = new AccionDefinida(0, 0, "", "");
EventoDefinido ElEvento = new EventoDefinido(0, 0, "", "");
//ACTIONS
ActionsSQLite base = new ActionsSQLite(context, "Actions", null,1);
SQLiteDatabase db1 = base.getReadableDatabase();
db1 = context.openOrCreateDatabase("Actions",SQLiteDatabase.OPEN_READONLY, null);
String query = "SELECT * FROM Actions WHERE Id = " + String.valueOf(position + 1);
Cursor c1 = db1.rawQuery(query, null);
try{
if(c1!=null){
int i = c1.getColumnIndexOrThrow("Id");
int j = c1.getColumnIndexOrThrow("IdAccionDefinida");
int k = c1.getColumnIndexOrThrow("IdEventoDefinido");
int l = c1.getColumnIndexOrThrow("Activa");
boolean esActiva;
//Nos aseguramos de que existe al menos un registro
while(c1.moveToNext()){
if (c1.getInt(l) == 0){
esActiva = false;
} else
{
esActiva = true;
}
//Recorremos el cursor hasta que no haya más registros
a = new Action(c1.getInt(i), c1.getInt(j), c1.getInt(k), esActiva);
}
}
else
Toast.makeText(context.getApplicationContext(),
"No hay nada :(", Toast.LENGTH_LONG).show();
}
catch (Exception e){
Log.i("bdActions", "Error al abrir o crear la base de datos" + e);
}
if(db1!=null){
db1.close();
}
//EVENTOS
EventosDefinidosSQLite base2 = new EventosDefinidosSQLite(this.context, "EventosDefinidos", null, 1);
SQLiteDatabase db2 = base2.getReadableDatabase();
db2 = context.openOrCreateDatabase("EventosDefinidos",SQLiteDatabase.OPEN_READONLY, null);
String query2 = "SELECT * FROM EventosDefinidos WHERE Id = " + a.getIdEventoDefinido();
Cursor c2 = db2.rawQuery(query2, null);
try{
if(c2!=null){
int h = c2.getColumnIndexOrThrow("Id");
int k = c2.getColumnIndexOrThrow("IdEvento");
int i = c2.getColumnIndexOrThrow("Nombre");
int j = c2.getColumnIndexOrThrow("Aux");
//Nos aseguramos de que existe al menos un registro
while(c2.moveToNext()){
//Recorremos el cursor hasta que no haya más registros
ElEvento = new EventoDefinido(c2.getInt(h), c2.getInt(k), c2.getString(i), c2.getString(j));
}
}
else
Toast.makeText(context.getApplicationContext(),
"No hay nada :(", Toast.LENGTH_LONG).show();
}
catch (Exception e){
Log.i("bdEventos", "Error al abrir o crear la base de datos" + e);
}
if(db2!=null){
db2.close();
}
//ACCIONES
AccionesDefinidasSQLite base3 = new AccionesDefinidasSQLite(context, "AccionesDefinidas", null,1);
SQLiteDatabase db3 = base3.getReadableDatabase();
db3 = context.openOrCreateDatabase("AccionesDefinidas", SQLiteDatabase.OPEN_READONLY, null);
String query3 = "SELECT * FROM AccionesDefinidas WHERE Id = " + String.valueOf(a.getIdAccionDefinida());
Cursor c3 = db3.rawQuery(query3, null);
try{
if(c3!=null){
int h = c3.getColumnIndexOrThrow("Id");
int k = c3.getColumnIndexOrThrow("IdAccion");
int i = c3.getColumnIndexOrThrow("Nombre");
int j = c3.getColumnIndexOrThrow("Aux");
//Nos aseguramos de que existe al menos un registro
while(c3.moveToNext()){
//Recorremos el cursor hasta que no haya más registros
LaAccion = new AccionDefinida(c3.getInt(h), c3.getInt(k), c3.getString(i), c3.getString(j));
}
}
else
Toast.makeText(context.getApplicationContext(),
"No hay nada :(", Toast.LENGTH_LONG).show();
}
catch (Exception e){
Log.i("bdAcciones", "Error al abrir o crear la base de datos" + e);
}
if(db3!=null){
db3.close();
}
// object item based on the position
// assign values if the object is not null
if(a != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.codigo.setText(String.valueOf(a.getId()));
viewHolder.codigo.setTag(a.getId());
viewHolder.accion.setText(LaAccion.getNombre());
viewHolder.evento.setText(ElEvento.getNombre());
viewHolder.UnSwitch.setChecked(a.getActiva());
Log.e("Position+1: "+ String.valueOf(position+1), "Id: "+ String.valueOf(a.getId()));
}
viewHolder.isChecked1 = viewHolder.UnSwitch.isChecked();
map.put(position, viewHolder.isChecked1);
viewHolder.UnSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("OnClick", "Se clickeó");
listaActions.get(position).setActiva(map.get(position));
Log.e("Listener del switch", "Modificó la action en la lista de la ActividadPrincipal");
int isActiva;
if(map.get(position) == true)
{
isActiva = 0;
Log.e("Listener del switch", "isActiva = 1");
map.put(position, false);
} else
{
isActiva = 1;
Log.e("Listener del switch", "isActiva = 0");
map.put(position, true);
}
String query = "UPDATE Actions SET Activa = " + String.valueOf(isActiva) + " WHERE Id = " + String.valueOf(position+1);
Log.e("Consulta:", query);
Log.e("Listener del switch", "query creado");
Log.e("La position debería ser", String.valueOf(position+1));
Log.e("Y el valor del map.get(position) es", String.valueOf(map.get(position)));
ActionsSQLite helper1 = new ActionsSQLite(context, "Actions", null, 1);
Log.e("Listener del switch", "Creo el helper");
SQLiteDatabase db = helper1.getWritableDatabase();
Log.e("Listener del switch", "obtenida la base escribible");
db.execSQL(query);
Log.e("Listener del switch", "Query ejecutado");
}
});
return convertView;
}
当我从该ArrayList中删除一个对象时,我会从这个对话框中删除它:
import java.util.ArrayList;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
public class DialogModificarAction extends DialogFragment
{
public interface DialogModificarActionListener {
}
private int getIndex(Spinner spinner, ArrayList<String> MiLista){
int index = 0;
for(int j = 0;j<=MiLista.size();j++){
if (spinner.getSelectedItem().equals(MiLista.get(j))){
index = j;
break;
}
}
return index;
}
private Button cancelButton;
private Button confirmButton;
private Button deleteButton;
private Spinner spinnerAccion;
private Spinner spinnerEvento;
private static Action ActionAModificar = null;
private ArrayList<EventoDefinido> ListaEventosDefinidos = new ArrayList<EventoDefinido>();
private ArrayList<AccionDefinida> ListaAccionesDefinidas = new ArrayList<AccionDefinida>();
private ArrayList<String> ListaNombresAccionesDefinidas = new ArrayList<String>();
private ArrayList<String> ListaNombresEventosDefinidos = new ArrayList<String>();
public DialogModificarAction()
{
// Empty constructor required for DialogFragment
}
@SuppressWarnings("unused")
private DialogModificarActionListener dialogListener;
//This is how you can supply your fragment with information
public static DialogModificarAction newInstance(ArrayList<Action> ListaActions, ArrayList<AccionDefinida> ListaAccionesDefinidas, ArrayList<EventoDefinido> ListaEventosDefinidos, Action ActionAModificar)
{
DialogModificarAction myDialog = new DialogModificarAction();
Bundle args = new Bundle();
args.putParcelableArrayList("ListaActions", ListaActions);
args.putParcelableArrayList("ListaAccionesDefinidas", ListaAccionesDefinidas);
args.putParcelableArrayList("ListaEventosDefinidos", ListaEventosDefinidos);
args.putParcelable("ActionAModificar", ActionAModificar);
myDialog.setArguments(args);
return myDialog;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0); // Le saca el título al DialogFragment
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.dialog_modif_baja_action, container);
//DECLARO LOS ELEMENTOS EN EL LAYOUT
ActionAModificar = getArguments().getParcelable("ActionAModificar");
ListaAccionesDefinidas = getArguments().getParcelableArrayList("ListaAccionesDefinidas");
ListaEventosDefinidos = getArguments().getParcelableArrayList("ListaEventosDefinidos");
spinnerAccion = (Spinner)view.findViewById(R.id.spinnerAccionDefinida);
spinnerEvento = (Spinner)view.findViewById(R.id.spinnerEventoDefinido);
AccionDefinida AccionTemporal;
for(int i = 0; i<= ListaAccionesDefinidas.size()-1;i++)
{
AccionTemporal = ListaAccionesDefinidas.get(i);
ListaNombresAccionesDefinidas.add(AccionTemporal.getNombre());
}
EventoDefinido EventoTemporal;
for(int i = 0; i<= ListaEventosDefinidos.size()-1;i++)
{
EventoTemporal = ListaEventosDefinidos.get(i);
ListaNombresEventosDefinidos.add(EventoTemporal.getNombre());
}
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, ListaNombresAccionesDefinidas);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerAccion.setAdapter(dataAdapter);
spinnerAccion.setSelection(ActionAModificar.getIdAccionDefinida()-1);
ArrayAdapter<String> dataAdapter2 = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, ListaNombresEventosDefinidos);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerEvento.setAdapter(dataAdapter2);
spinnerEvento.setSelection(ActionAModificar.getIdEventoDefinido()-1);
//Setup cancel button listener
cancelButton = (Button) view.findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
//Cerrar diálogo y no hacer nada
getDialog().dismiss();
}
});
//Setup confirm button listener
confirmButton = (Button) view.findViewById(R.id.confirmButton);
confirmButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
//Obtengo los ids de la accion y el evento
int IdAccionDefinidaSeleccionada;
int IdEventoDefinidoSeleccionado;
IdAccionDefinidaSeleccionada = ListaAccionesDefinidas.get(getIndex(spinnerAccion, ListaNombresAccionesDefinidas)).getId();
IdEventoDefinidoSeleccionado = ListaEventosDefinidos.get(getIndex(spinnerEvento, ListaNombresEventosDefinidos)).getId();
ActionAModificar.setIdAccionDefinida(IdAccionDefinidaSeleccionada);
ActionAModificar.setIdEventoDefinido(IdEventoDefinidoSeleccionado);
ActividadPrincipal.listaActions.get(ActionAModificar.getId()).setIdAccionDefinida(IdAccionDefinidaSeleccionada);
ActividadPrincipal.listaActions.get(ActionAModificar.getId()).setIdEventoDefinido(IdEventoDefinidoSeleccionado);
//Agrego la Action a la base de datos
ActionsSQLite helper1 = new ActionsSQLite(getActivity(), "Actions", null, 1);
SQLiteDatabase db = helper1.getWritableDatabase();
String myQuery = "UPDATE Actions SET IdAccionDefinida = " + String.valueOf(IdAccionDefinidaSeleccionada) + ", IdEventoDefinido = " + String.valueOf(IdEventoDefinidoSeleccionado) + " WHERE Id = " + String.valueOf(ActionAModificar.getId());
db.execSQL(myQuery);
ActividadPrincipal parent = (ActividadPrincipal) getActivity();
parent.listView.invalidateViews();
//Cerrar diálogo
getDialog().dismiss();
}
});
deleteButton = (Button) view.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
String query = "DELETE FROM Actions WHERE Id = " + String.valueOf(ActionAModificar.getId());
ActionsSQLite helper1 = new ActionsSQLite(getActivity(), "Actions", null, 1);
SQLiteDatabase db = helper1.getWritableDatabase();
db.execSQL(query);
Log.e("Listener del switch", "Query ejecutado");
ActividadPrincipal.listaActions.remove(ActionAModificar.getId()-1);
ActividadPrincipal.adapterActions.notifyDataSetChanged();
//Cerrar diálogo
getDialog().dismiss();
}
});
return view;
}
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if (activity instanceof DialogModificarActionListener)
{
dialogListener = (DialogModificarActionListener) activity;
}
else
{
throw new ClassCastException(activity.toString() + " must implement dialogListener.DialogActionsListener");
}
}
@Override
public void onDismiss(DialogInterface dialog) {
ActividadPrincipal parent = (ActividadPrincipal) getActivity();
parent.ActualizarActions();
}
}
答案 0 :(得分:1)
如果更改列表中的数据,则必须调用适配器的notifyDataSetChanged
方法才能正常运行。
除此之外您可能还有其他错误,但绝对需要notifyDataSetChanged
。首先添加,然后在遇到问题时继续进行故障排除。
编辑:既然您已经展示了自己的代码,我就不会感到惊讶它不起作用。你显然混淆了几个应该是独立实体的概念。特别是,您不应该从适配器进行数据库访问。
我不愿意花时间尝试完全理解您的代码,坦率地说,这是一个混乱,所以让我来描述如何应该接近。< / p>
有两种基本情景。在第一个场景中,您有一个对象列表,并希望在ListView中显示它们。在第二个场景中,您在数据库中有对象,并希望在ListView中显示它们。这两种情况可能不应该是混合的。
在第一个(更简单的)场景中,您只需构造一个ListAdapter,并将列表提供给适配器。在这种情况下,如果从列表中删除项目,则还必须调用ListAdapter的notifyDataSetChanged()方法。如果您希望此删除超出当前的应用程序运行范围,您可以自行更新列表的原始来源。
在第二种情况下,您可以从数据库中获取Cursor,可能使用CursorLoader,可能是从ContentProvider获得的。然后,您将创建一个CursorAdapter,并将其与ListView一起使用。在这种情况下,您要求ContentProvider从数据库中删除该项,这将自动使ContentProvider更新Cursor,并将通知您的活动。然后将新光标提供给CursorAdapter,并调用它的notifyDataSetChanged方法。
网上有很多关于如何执行此操作的教程 - 我建议您阅读并查看一些示例。