2015-10-25 5 views
0

Я проверил много вопросов переполнения стека, и никто из них не помог. Как обновить список ListView после удаления элемента с помощью onLongClickListener? Как вы увидите, ни adapter.notifyDataSetChanged(), ни listView.invalidateViews() не работают.Обновить ListView после удаления

Это реализация с помощью только необходимых методов для определения идеи.

public class MainActivity extends AppCompatActivity { 
public FloatingActionButton fabAddWord; 
public Toolbar toolbar; 
public ListView listView; 
private RjecnikCursorAdapter adapter; 

private RjecnikDB dbRjecnik; 
private SQLiteDatabase db; 
private Cursor cursor; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    fabAddWord = (FloatingActionButton) findViewById(R.id.fabAddWord); 
    listView = (ListView) findViewById(R.id.listView); 

    dbRjecnik = new RjecnikDB(this); 
    db = dbRjecnik.getWritableDatabase(); 
    String query = "SELECT * FROM " + RjecnikDB.TABLE; 
    cursor = db.rawQuery(query, null); 

    adapter = new RjecnikCursorAdapter(this, cursor); 
    listView.setAdapter(adapter); 

    listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
     @Override 
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
      deleteOnLongClick(cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC))); 

      adapter.notifyDataSetChanged(); 
      listView.invalidateViews(); 

      return true; 
     } 
    }); 
} 

public void deleteOnLongClick(String rijec) { 
    SQLiteDatabase db = dbRjecnik.getWritableDatabase(); 
    db.delete(RjecnikDB.TABLE, RjecnikDB.COLUMN_RIJEC + " = ?", new String[] {rijec}); 

    this.adapter.notifyDataSetChanged(); 
    this.listView.invalidateViews(); 

    db.close(); 
} 

CustomAdapter

public class RjecnikCursorAdapter extends CursorAdapter { 

public RjecnikCursorAdapter (Context context, Cursor cursor) { 
    super(context, cursor, 0); 
} 

@Override 
public View newView(Context context, Cursor cursor, ViewGroup parent) { 
    return LayoutInflater.from(context).inflate(R.layout.item_word, parent, false); 
} 

@Override 
public void bindView(View view, Context context, Cursor cursor) { 
    TextView tvSingleLineWord = (TextView) view.findViewById(R.id.tvSingleLineWord); 

    // Extract properties from cursor 
    String rijec = cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC)); 

    // Populate fields with extracted properties 
    tvSingleLineWord.setText(rijec); 
} 

}

+0

Я верю, вы просто удалить из БД не от адаптера? – Dhina

+0

Когда я перехожу к другому действию и возвращаюсь, удаленный текст просматривается. Итак, как мне удалить из адаптера? – ridjis

ответ

0

Адаптер имеет кэш данных, поэтому данные в ListView не будет при изменении данных в базе данных. Вы должны изменить курсор.

@Override 
public void changeCursor(Cursor cursor) { 
    mIndexer.setCursor(cursor); 
    super.changeCursor(cursor); 
} 

код положить ниже в ваш OnItemLongClickListener

cursor = db.rawQuery(query, null); 
adapter.changeCurosr(cursor); 
+0

'db.rawQuery (query, null); ' Первый запрос param должен быть' SELECT * FROM TABLE_NAME'? – ridjis

+0

Да, поэтому вы можете установить 'String query =" SELECT * FROM "+ RjecnikDB.TABLE;' to 'final' – zhenghuiyan

+0

В случае большой базы данных часто будет запрашиваться скорость изменения? – ridjis

0

Вы должны использовать только notifyDataSetChanged(), чтобы обновить данные ListView, invalidateViews() будет только перерисовывать видимые элементы еще ничего на них не изменилось (например, изменение шрифта).

Обратите внимание, что рекомендуется запускать notifyDataSetChanged() в потоке пользовательского интерфейса.

EDIT 2: вы можете использовать BaseAdapter вместо CursorAdapter, как показано ниже

public class RjecnikCursorAdapter extends BaseAdapter { 
    private Activity activity; 
    private LayoutInflater inflater; 
    private List<String> rjecnikList; 


    public RjecnikCursorAdapter(Activity activity, List<String> rjecnikList) { 
     this.activity = activity; 
     this.rjecnikList = rjecnikList; 
    } 

    @Override 
    public int getCount() { 
     return rjecnikList.size(); 
    } 

    @Override 
    public Object getItem(int location) { 
     return rjecnikList.get(location); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     if (inflater == null) 
      inflater = (LayoutInflater) activity 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     if (convertView == null) 
      convertView = inflater.inflate(R.layout.item_word, null); 

     TextView tvSingleLineWord = (TextView) view.findViewById(R.id.tvSingleLineWord); 

     tvSingleLineWord.setText(String.valueOf(rjecnikList.get(position))); 


     return convertView; 
    } 

} 

И в своей деятельности:

public class MainActivity extends AppCompatActivity { 
    public FloatingActionButton fabAddWord; 
    public Toolbar toolbar; 
    public ListView listView; 
    public List<String> mylist; 
    private RjecnikCursorAdapter adapter; 

    private RjecnikDB dbRjecnik; 
    private SQLiteDatabase db; 
    private Cursor cursor; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     fabAddWord = (FloatingActionButton) findViewById(R.id.fabAddWord); 
     listView = (ListView) findViewById(R.id.listView); 

     dbRjecnik = new RjecnikDB(this); 
     db = dbRjecnik.getWritableDatabase(); 
     String query = "SELECT * FROM " + RjecnikDB.TABLE; 
     cursor = db.rawQuery(query, null); 
     mylist = new ArrayList<>(); 

     if (cursor.moveToFirst()){ 

do{ 
//change this with your column data 
     String data = cursor.getString(cursor.getColumnIndex("data"); 

     mylist.add(data); 

    }while(cursor.moveToNext()); 

} 

cursor.close(); 
     adapter = new RjecnikCursorAdapter(this, mylist); 
     listView.setAdapter(adapter); 

     listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
      @Override 
      public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
       deleteOnLongClick(cursor.getString(cursor.getColumnIndex(RjecnikDB.COLUMN_RIJEC))); 
       mylist.remove(position); 
       adapter.notifyDataSetChanged(); 
       listView.invalidateViews(); 

       return true; 
      } 
     }); 
    } 

    public void deleteOnLongClick(String rijec) { 
     SQLiteDatabase db = dbRjecnik.getWritableDatabase(); 
     db.delete(RjecnikDB.TABLE, RjecnikDB.COLUMN_RIJEC + " = ?", new String[] {rijec}); 

     this.adapter.notifyDataSetChanged(); 
     this.listView.invalidateViews(); 

     db.close(); 
    } 
+0

Все еще не работает. Я добавил 'новую тему (новый Runnable() { @Override общественности недействительным запуска() { MainActivity.this.runOnUiThread (новый Runnable() { @Override общественности недействительным запуска() { adapter.notifyDataSetChanged(); } } } }). Start(); ' и только после того, как я перейду к другому действию и вернусь, удаленный текст будет удален. – ridjis

+0

1- пожалуйста, можете ли вы отредактировать свой пост, добавив код адаптера? 2- для запуска кода в потоке пользовательского интерфейса вам не нужно использовать другой поток, просто runOnUiThrad –

+0

У меня нет метода удаления для listView. Лишь немногие, которые на самом деле пытаются удалить вид, например 'removeView, removeViewAt, removeFooterView' и т. Д. И все они приводят к ошибкам, например' removeViewAt (int) не поддерживается в AdapterView' – ridjis

Смежные вопросы