2012-02-13 2 views
0

Я борюсь с обновлением своего ListView после того, как пользователь удалил строку из таблицы source-SQLite.Обновить ListView после взаимодействия с пользователем

Я искал несколько дней для решения и обнаружил несколько мест, которые рекомендуют использовать notifyDataSetChanged(), но я не могу понять, где его разместить и как его использовать.

Я пытаюсь использовать BaseAdapter, но я не уверен, посмотрев на LogCat, что это сделано правильно.

Это код, я использую:

ArrayList<HashMap<String,String>> results = new ArrayList<HashMap<String,String>>(); 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    openAndQueryFav(); 
    displayResultList(); 


    ListView lv = getListView(); 
    lv.setTextFilterEnabled(true); 

    lv.setOnItemClickListener(new OnItemClickListener() { 

     public void onItemClick(AdapterView<?> parent, View view, 
      int position, long id) { 
       HashMap<String, String> item = (HashMap<String, String>) parent.getAdapter().getItem(position); 
       String Start = item.get("Start").toString(); 
       String Name = item.get("Name").toString(); 
       try{ 
        DBAdapter dbHelper = new DBAdapter(getBaseContext()); 
        newDB = dbHelper.getWritableDatabase(); 
        Cursor favorite = newDB.rawQuery("SELECT Start FROM " + 
          tableFav + " WHERE Start='" + Start + "'", null); 
        favorite.moveToFirst(); 

         if(favorite.getCount() > 0){ 
          newDB.execSQL("DELETE FROM " + 
            tableFav + " WHERE start='" + Start + "'"); 
          HeaderViewListAdapter adapterwrap = (HeaderViewListAdapter) parent.getAdapter(); 
          BaseAdapter adapter = (BaseAdapter) adapterwrap.getWrappedAdapter(); 

          adapter.notifyDataSetChanged(); 


         }else{ 

         } 
       }catch(Exception e){ 

        Log.d("Events", "catch, exception." + e.toString()); 
       }finally{ 

        newDB.close(); 
       } 
      } 
     }); 

} 



private void displayResultList() { 

    ListAdapter adapter = new SimpleAdapter(
      this, 
      results, 
      R.layout.list, 
      new String[] {"Start","Name","date"}, 
      new int[] {R.id.item_id,R.id.item_name,R.id.item_date} 
      ); 
    setListAdapter(adapter); 

    } 

я должен делать что-то ужасное неправильно! Потому что, когда я пытаюсь запустить его я получаю это в LogCat:

02-14 00:28:54.777: D/Events(9172): catch, exception.java.lang.ClassCastException: android.widget.SimpleAdapter 

И если я пытаюсь поставить:

HeaderViewListAdapter adapterwrap = (HeaderViewListAdapter) parent.getAdapter(); 
BaseAdapter adapter = (BaseAdapter) adapterwrap.getWrappedAdapter(); 

вне попытки {} эта ошибка в LogCat:

02-13 23:04:53.107: E/AndroidRuntime(9066): FATAL EXCEPTION: main 
02-13 23:04:53.107: E/AndroidRuntime(9066): java.lang.ClassCastException: android.widget.SimpleAdapter 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at com.myapplication.Favorite$1.onItemClick(Favoritter.java:74) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.widget.AdapterView.performItemClick(AdapterView.java:284) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.widget.ListView.performItemClick(ListView.java:3382) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.widget.AbsListView$PerformClick.run(AbsListView.java:1696) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.os.Handler.handleCallback(Handler.java:587) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.os.Handler.dispatchMessage(Handler.java:92) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.os.Looper.loop(Looper.java:144) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at android.app.ActivityThread.main(ActivityThread.java:4937) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at java.lang.reflect.Method.invoke(Method.java:521) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
02-13 23:04:53.107: E/AndroidRuntime(9066):  at dalvik.system.NativeStart.main(Native Method) 

Может ли кто-нибудь указать мне в правильном направлении, чтобы обновить список после выполнения задачи?

Спасибо!

ответ

0

Я нашел решение моей проблемы.

Обнаружено working example, что я использовал для понимания проблемы.

Главное отличие заключается в том, что я использую «requery()» на курсоре после внесения изменений в базу данных, которую я хотел.

Это код, после того, как я сделал изменения, которые были необходимы:

newDB = new DBAdapter(this.getApplicationContext()); 

     c = newDB 
     .getWritableDatabase() 
     .rawQuery("SELECT _ID, Start, Name, Time, Fav FROM " + 
       tableName + " WHERE Fav='1'" , null); 
     ListAdapter adapter = new SimpleCursorAdapter(
       this, 
       R.layout.list, c, 
       new String[] {"Start","Name","Time"}, 
       new int[] {R.id.item_id,R.id.item_name,R.id.item_time} 
       ); 
     setListAdapter(adapter); 

     ListView lv = getListView(); 
     lv.setTextFilterEnabled(true); 

     lv.setOnItemClickListener(new OnItemClickListener() { 

      public void onItemClick(AdapterView<?> parent, View view, 
       int position, long id) { 
       String Start = c.getString(c.getColumnIndex("Start")); 
        try{ 
         newDB.getWritableDatabase().execSQL("UPDATE " + 
             tableName + " SET Fav='0' WHERE Start='" + Start + "'"); 
         c.requery(); 

        }catch(Exception e){ 

         Log.d("Events", "catch, exception." + e.toString()); 
        }finally{ 

        } 
       } 
      }); 

Tnx вам @Simon за попытку помочь мне вместе!

0

Все, что обновляет пользовательский интерфейс, должно запускаться в потоке пользовательского интерфейса. Попробуй это.

runOnUiThread(new Runnable() { 
    public void run() { 
     adapter.notifyDataSetChanged(); 
    } 
}); 

Если основной поставщик данных адаптера изменяется непосредственно, как в вашем случае при изменении базы данных, адаптер должен быть уведомлен. Более чистый способ сделать это - расширить класс адаптера и переопределить вставку, добавление, удаление и т. Д. Таким образом, вам не нужно делать какие-либо уведомления, поскольку адаптер знает, что он поддерживает данные, был изменен и будет уведомлять о каких-либо связанных представлениях автоматически. Другим преимуществом такого подхода является то, что вы можете изменить базовую реализацию поставщика данных, например, переместить его в XML, без изменений кода вне адаптера.

+0

Я попытался реализовать ваше предложение о 'notifyDataSetChanged()', но я обнаружил, что он не поддерживается Hashmap. Вы предлагаете мне расширить класс адаптера и переопределить удаление, как это сделать? жаль начинающих вопросов. – Christoffer