Вопрос

I am running into an issue where I cannot get the screen to dynamically update after I "swipe-to-dismiss" an item from my list. The objects are successfully deleted from the database, but since the screen never updates it gives me the ability to keep swiping to dismiss and eventually causes an IndexOutOfBoundsException.

I have tried every combination of .remove(), .notifyDataSetChanged(), and I am to the point where I am trying to look into other options.

Do you think that my problem may be stemming from the way that I am populating the List lstEvents? ... I am using a lstEvents = db.getAllContacts();

THE MAIN ACTIVITY REFLECTS WORKING CODE

MainActivity

    public class MainActivity extends ListActivity implements OnClickListener {

    List<Event> lstEvents = new ArrayList<Event>();

   EventAdapter adapter;
    DatabaseHandler db;

    // detail view
    TextView tvTitle, tvTime, tvDate;
    ImageView ivPic;

    ImageButton add;

    String title;
    String date;
    String time;

    Context context;


    static final int PICK_CONTACT_REQUEST = 0;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        // // get detail controls
        tvTitle = (TextView) findViewById(R.id.textViewTitle);
        tvDate = (TextView) findViewById(R.id.textViewDate);
        tvTime = (TextView) findViewById(R.id.textViewTime);
        ivPic = (ImageView) findViewById(R.id.imageView1);

        add = (ImageButton) findViewById(R.id.add);
        add.setOnClickListener(this);

        // /////////////////////////////DATABASE/////////////////////////////////////////////
        db = new DatabaseHandler(this);
        // /////////////////////////////DATABASE/////////////////////////////////////////////

        // ///////////////////////////////LISTVIEW////////////////////////////////////////
        // Create the adapter to convert the array to views
        adapter = new EventAdapter(this, lstEvents);

        // attach adapter to a list view
        ListView listView = getListView();
        listView.setAdapter(adapter);

        context = this;

        SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(
                listView,
                new SwipeDismissListViewTouchListener.DismissCallbacks() {


//                  DatabaseHandler db = new DatabaseHandler(context);
//                  EventAdapter adapter = new EventAdapter(context,
//                          lstEvents);


                    @Override
                    public boolean canDismiss(int position) {
                        return true;
                    }

                    @Override
                    public void onDismiss(ListView listView,
                            int[] reverseSortedPositions) {
                        for (int position : reverseSortedPositions) {

                           Event event = adapter.getItem(position);

                           adapter.remove(event);
                           db.deleteEvent(event);

                            for (Event ev : db.getAllContacts()) {
                                String log = "Id: " + ev.get_Id() + " ,Title: "
                                        + ev.get_title() + " ,Date: " + ev.get_date()
                                        + " ,RESOURCEID: " + ev.get_image();
                                // Writing Contacts to log
                                Log.e("````````````````ON DISMISS`````````````` ", log);

                            }

                        }
                        adapter.notifyDataSetChanged();

                    }
                });

        listView.setOnTouchListener(touchListener);
        // Setting this scroll listener is required to ensure that during

        // // ListView scrolling,
        // // we don't look for swipes.
        listView.setOnScrollListener(touchListener.makeScrollListener());


        lstEvents = db.getAllContacts();
        adapter.clear();
        adapter.addAll(lstEvents);
        adapter.notifyDataSetChanged();

        for (Event ev : db.getAllContacts()) {
            String log = "Id: " + ev.get_Id() + " ,Title: "
                    + ev.get_title() + " ,Date: " + ev.get_date()
                    + " ,RESOURCEID: " + ev.get_image();
            // Writing Contacts to log

            Log.e("++++++++++++++++ONCREATE+++++++++++++++ ", log);

        }

    }

    // @Override
    protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    adapter.clear();
    lstEvents = db.getAllContacts();
    adapter.addAll(lstEvents);
    adapter.notifyDataSetChanged();

        for (Event ev : db.getAllContacts()) {
            String log = "Id: " + ev.get_Id() + " ,Title: "
                    + ev.get_title() + " ,Date: " + ev.get_date()
                    + " ,RESOURCEID: " + ev.get_image();
            // Writing Contacts to log

            Log.e("++++++++++++++++ONRESUME+++++++++++++++ ", log);

        }


    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case R.id.add:
            Intent intent = new Intent(this, CreateActivity.class);
            startActivityForResult(intent, 100);
            break;
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);


        // attach adapter to a list view
        ListView listView = getListView();
        listView.setAdapter(adapter);

        if (requestCode == 100) {
            if (resultCode == RESULT_OK) {
                Bundle b = data.getExtras();
                title = b.getString("TITLE");
                time = b.getString("TIME");
                date = b.getString("DATE");

                Bitmap bitmap = b.getParcelable("BITMAP");

                // ///CONVERTING A BITMAP TO A BYTE[]
                byte[] image = null;
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
                image = bos.toByteArray();
                // ///////

                // /////////////////////////////DATABASE/////////////////////////////////////////////
                /**
                 * CRUD OPERATIONS
                 */

                Log.e("Insert: ", "Inserting ..");
                db.addEvent(new Event((int) Math.floor(Math.random() * 101),
                        title, time, date, image));

                // Reading all contacts
                Log.e("Reading: ", "Reading all contacts..");

                lstEvents = db.getAllContacts();
                adapter.clear();
                adapter.addAll(lstEvents);
                adapter.notifyDataSetChanged();

                // logging all events

                for (Event ev : db.getAllContacts()) {
                    String log = "Id: " + ev.get_Id() + " ,Title: "
                            + ev.get_title() + " ,Date: " + ev.get_date()
                            + " ,RESOURCEID: " + ev.get_image();
                    // Writing Contacts to log
                    Log.e("-----------------ON ACTIVITY RESULT-------------- ", log);

                }

                // /////////////////////////////DATABASE/////////////////////////////////////////////
            }

        }
    }
}

EventAdapter

public class EventAdapter extends ArrayAdapter<Event> {

// View lookup cache
private static class ViewHolder {
    //adding drawable to imageview
    ImageView img;
    TextView title;
    TextView time;
    TextView date;
}

public EventAdapter(Context context, List<Event> objects) {
    super(context, R.layout.date_detail, objects);
    // TODO Auto-generated constructor stub
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Get the data item for this position
    Event event = getItem(position);
    // Check if an existing view is being reused, otherwise inflate the view
    ViewHolder viewHolder;
    if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.date_detail, parent, false);
        viewHolder.title = (TextView) convertView
                .findViewById(R.id.textViewTitle);
        viewHolder.time = (TextView) convertView
                .findViewById(R.id.textViewTime);
        viewHolder.date = (TextView) convertView
                .findViewById(R.id.textViewDate);

        //adding drawable to imageview
        viewHolder.img = (ImageView) convertView
                .findViewById(R.id.imageView1);


        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    // Populate the data into the template view using the data object
    viewHolder.title.setText(event._title);
    viewHolder.time.setText(event._time);
    viewHolder.date.setText(event._date);

    //convert from byte array to bitmap               
    Bitmap bitmap = convertByteArrayToBitmap(event._image);
    // CONVERT BITMAP TO DRAWABLE
    viewHolder.img.setImageBitmap(bitmap);
    // Return the completed view to render on screen
    return convertView;
}

public static Bitmap convertByteArrayToBitmap(
        byte[] byteArrayToBeCOnvertedIntoBitMap)
    {
        Bitmap bitmap = BitmapFactory.decodeByteArray(
            byteArrayToBeCOnvertedIntoBitMap, 0,
            byteArrayToBeCOnvertedIntoBitMap.length);
        return bitmap;
    }
 }

DATABASE HANDLER

public DatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    String CREATE_EVENTS_TABLE = "CREATE TABLE " + TABLE_EVENTS + "("
            + KEY_ID + " INTEGER," + KEY_TITLE + " TEXT,"
            + KEY_TIME + " TEXT," + KEY_DATE + " TEXT," + KEY_IMAGE + " BLOB" + ")";
    db.execSQL(CREATE_EVENTS_TABLE);

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // Drop older table if existed
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_EVENTS);

    // Create tables again
    onCreate(db);

}

/**
 * All CRUD(Create, Read, Update, Delete) Operations
 */


//adding an event (NEEDS TO ADD DRAWABLE)
 public void addEvent(Event event) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, event.get_Id()); //Event ID
        values.put(KEY_TITLE, event.get_title()); // Event Title
        values.put(KEY_TIME, event.get_time()); // Event Time
        values.put(KEY_DATE, event.get_date()); // Event Date
        values.put(KEY_IMAGE, event.get_image()); // Event RESOURCEID

        // Inserting Row
        db.insert(TABLE_EVENTS, null, values);
        db.close(); // Closing database connection
    }

   // Getting single contact
   public Event getEvent(int id) {
       SQLiteDatabase db = this.getReadableDatabase();

       Cursor cursor = db.query(TABLE_EVENTS, new String[] { KEY_ID,
               KEY_TITLE, KEY_TIME, KEY_DATE, KEY_IMAGE }, KEY_ID + "=?",
               new String[] { String.valueOf(id) }, null, null, null, null);
       if (cursor != null)
           cursor.moveToFirst();

       Event event = new Event(Integer.parseInt(cursor.getString(0)),
               cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getBlob(4));
       // return contact
       return event;
   }


    // Getting All Contacts
   public List<Event> getAllContacts() {
      List<Event> eventList = new ArrayList<Event>();
      // Select All Query
      String selectQuery = "SELECT  * FROM " + TABLE_EVENTS;

      SQLiteDatabase db = this.getWritableDatabase();
      Cursor cursor = db.rawQuery(selectQuery, null);

      // looping through all rows and adding to list
      if (cursor.moveToFirst()) {
          do {

              Event event = new Event();
              event.set_Id(Integer.parseInt(cursor.getString(0)));
              event.set_title(cursor.getString(1));
              event.set_time(cursor.getString(2));
              event.set_date(cursor.getString(3));                          
              event.set_image(cursor.getBlob(4));
              eventList.add(event);
          } while (cursor.moveToNext());
      }

      // return contact list
      return eventList;
  }

// Getting event Count
    public int getEventsCount() {
        String countQuery = "SELECT  * FROM " + TABLE_EVENTS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        cursor.close();

        // return count
        return cursor.getCount();
    }

 // Updating single contact
    public int updateEvent(Event event) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_TITLE, event.get_title());
        values.put(KEY_TIME, event.get_time());
        values.put(KEY_DATE, event.get_date());

        // updating row
        return db.update(TABLE_EVENTS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(event.get_Id()) });
    }

    // Deleting single contact
    public void deleteEvent(Event event) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_EVENTS, KEY_ID + " = ?",
                new String[] { String.valueOf(event.get_Id()) });
        db.close();
    }
Это было полезно?

Решение

The problem is that you're defining a second adapter variable, here

SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView,
    new SwipeDismissListViewTouchListener.DismissCallbacks()
    {
        DatabaseHandler db = new DatabaseHandler(context);
        EventAdapter adapter = new EventAdapter(context, lstEvents); // <--

The ListView is bound to the "old" adapter. By changing the contents of lstEvents, you're basically changing the "true" adapter's backing array, without notifying it of the changes.

The fix would be to remove those instances, and then just using this to delete:

Event evt = adapter.getItem(position);
db.deleteEvent(evt); // to delete from the DB
adapter.remove(evt); // to remove from the adapter

That should work (ArrayAdapter.remove() calls notifyDataSetChanged() automatically). Do not delete from both the adapter and lstEvents, since those actually point to the same data.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top