2013-05-31 70 views
2

我一直在研究Android中的個人項目,並且遇到了關於使用ListView的Activity的奇怪情況。問題的基礎是我有一個項目列表,每個項目有2個按鈕,編輯和刪除。現在我正在執行刪除按鈕,它可以在功能上工作,但不會正確更新ListView。相反,它會將剛刪除的內容放在列表的頂部。無論什麼時候我轉向這個活動,它當然都會刷新。在OnClickListener裏面刷新Android ListView數據

現在在自定義BaseAdapter中檢測到Delete按鈕,當我調用notifyDataSetChanged時,上述情況發生,而不是刪除現在已刪除的項目。我該如何正確更新適配器類中的列表?

我意識到有關於此的一些問題,但我沒有能夠整合它們,我認爲可能工作的解決方案並不能真正解釋它們是如何工作的;我正在使用這個項目來更多地瞭解Android應用程序的開發,所以我希望有一些解釋層次的答案,當然,任何幫助當然是讚賞! 謝謝!

下面是相關的代碼。請注意,這是一個未完成的項目,所以它裏面有一些未使用/不完整的東西。請忽略這些。

EditItemsActivity:

package com.example.mybudget; 

import java.util.List; 

import android.annotation.SuppressLint; 
import android.app.Activity; 
import android.os.Build; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.GestureDetector; 
import android.view.GestureDetector.OnGestureListener; 
import android.view.Menu; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ListView; 

public class EditItemsActivity extends Activity implements OnGestureListener{ 

    private DatabaseHandler db; 
    private List<DataPoint> dpList; 
    private EditItemsAdapter adapter; 
    private ListView lv; 
    private GestureDetector gestureDetector; 

    @SuppressLint("NewApi") 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_edit_items); 
     // Show the Up button in the action bar. 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
      getActionBar().setDisplayHomeAsUpEnabled(true); 
     db = new DatabaseHandler(this); 
     dpList = db.allDataThisMonth(); 
     lv = (ListView) findViewById(R.id.edititems); 
     adapter = new EditItemsAdapter(this, R.id.edititems, dpList); 
     lv.setAdapter(adapter); 
     gestureDetector = new GestureDetector(getBaseContext(), this); 

//  buttonDelete.setVisibility(View.GONE); 
    } 

    public void refreshList() 
    { 
     adapter.notifyDataSetChanged(); 
    } 


    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_edit_items, menu); 
     return true; 
    } 


    @Override 
    public boolean onDown(MotionEvent e) { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    public void onDelete() 
    { 

    } 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
      float velocityY) 
    { 
//  Log.d("Swipe", "" + velocityX + ", " + velocityY); 
//  if(velocityX > 200 && velocityY < 50 && velocityY > -50) 
//  { 
//   buttonEdit.setVisibility(View.GONE); 
//   buttonDelete.setVisibility(View.VISIBLE); 
//  } 
//  else if(velocityX < -200 && velocityY < 50 && velocityY > -50) 
//  { 
//   buttonDelete.setVisibility(View.GONE); 
//   buttonEdit.setVisibility(View.VISIBLE); 
//  } 
     return false; 
    } 


    @Override 
    public void onLongPress(MotionEvent e) { 
     // TODO Auto-generated method stub 

    } 


    @Override 
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 
      float distanceY) { 
     // TODO Auto-generated method stub 
     return false; 
    } 


    @Override 
    public void onShowPress(MotionEvent e) { 
     // TODO Auto-generated method stub 

    } 


    @Override 
    public boolean onSingleTapUp(MotionEvent e) { 
     // TODO Auto-generated method stub 
     return false; 
    } 

} 

而這裏的適配器類:

package com.example.mybudget; 

import java.text.NumberFormat; 
import java.util.List; 

import android.app.Activity; 
import android.content.Intent; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.TextView; 

public class EditItemsAdapter extends BaseAdapter implements OnClickListener{ 
    private List<DataPoint> dpList; 
    private Activity activity; 
    private DatabaseHandler db; 

    public EditItemsAdapter(Activity a) 
    { 
     activity = a; 
    } 

    public EditItemsAdapter(Activity a, int textViewResourceId, List<DataPoint> dpList) 
    { 
     super(); 
     this.dpList = dpList; 
     activity = a; 
     db = new DatabaseHandler(activity); 
    } 

    public static class ViewHolder 
    { 
     public TextView item1; 
     public TextView item2; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     View v = convertView; 
     //ViewHolder holder; 
     NumberFormat format = NumberFormat.getCurrencyInstance(); 

     if (v == null) 
     { 
//   LayoutInflater vi = 
//     (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      LayoutInflater vi = activity.getLayoutInflater(); 
      v = vi.inflate(R.layout.edit_grid_items, null); 
//   holder = new ViewHolder(); 
//   holder.item1 = (TextView) v.findViewById(R.id.edit_item_name); 
//   holder.item2 = (TextView) v.findViewById(R.id.edit_item_cost); 
//   v.setTag(holder); 
      TextView tv1 = (TextView)v.findViewById(R.id.edit_item_name); 
      TextView tv2 = (TextView)v.findViewById(R.id.edit_item_cost); 
      Button edit = (Button)v.findViewById(R.id.edit_item_button); 
      Button delete = (Button)v.findViewById(R.id.delete_item_button); 
      final DataPoint dp = dpList.get(position); 
      tv1.setText(dp.getName()); 
      tv2.setText(Float.toString(dp.getCost())); 
      delete.setOnClickListener(new OnClickListener() 
      { 
       @Override 
       public void onClick(View v) 
       { 
        db.deleteRowByKey(dp); 
        ((EditItemsActivity) activity).refreshList(); 
       } 
      }); 
     } 
//  else 
//   holder = (ViewHolder)v.getTag(); 
//  if(dp != null) 
//  { 
//   holder.item1.setText(dp.getName()); 
//   holder.item2.setText(format.format(dp.getCost())); 
//  } 
     return v; 
    } 

    @Override 
    public int getCount() { 
     // TODO Auto-generated method stub 
     return dpList.size(); 
    } 

    @Override 
    public DataPoint getItem(int position) { 
     // TODO Auto-generated method stub 
     return dpList.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     // TODO Auto-generated method stub 
     return dpList.size(); 
    } 

    @Override 
    public void onClick(View v) { 
     // TODO Auto-generated method stub 

    } 
} 

編輯: 該解決方案所涉及的通貨膨脹的解釋,亞當提供,但需要dpList的完整覆育的

dpList = db.allDataThisMonth(); 

那個建議特德。

回答

3

在你的適配器的getView方法,你檢查if (convertView == null),如果它是空你膨脹的新觀點。如果它是而不是 null,那麼您只是返回提供的非空視圖。

供給到getView方法的convertView是已經被顯示的緩存的視圖。你應該重新使用它(如果它是一個有效的視圖 - 你可能在你的列表中有多個不同的視圖),而不是膨脹一個新的視圖。您忘記更新相應位置的內容。

那麼,如何解決它?只要通貨膨脹後關閉if (v == null)

if (v == null) 
{ 
    LayoutInflater vi = activity.getLayoutInflater(); 
    v = vi.inflate(R.layout.edit_grid_items, null); 
} 

編輯:阿努普所指出的,你還需要更新您的dpList變量或將保持在給定位置返回相同的數值。您可以在點擊監聽器中執行此操作:

delete.setOnClickListener(new OnClickListener() 
{ 
    @Override 
    public void onClick(View v) 
    { 
     db.deleteRowByKey(dp); 
     dpList.remove((Integer)v.getTag()); 
     ((EditItemsActivity) activity).refreshList(); 

    } 
}); 
// Required so we know which index to remove from our dpList. 
delete.setTag(position); 
+0

感謝您對通貨膨脹的解釋!事實證明,這是問題的核心,儘管由於某種原因,我不得不完全重新填充列表(使用remove的解決方案由於某種原因而不起作用)。我將這個標記爲解決方案,因爲我不明白的主要問題是通貨膨脹,因爲我已經試圖在沒有這種改變的情況下重新填充名單。 – Mike

+1

不用擔心!起初我也遇到了一些麻煩。至於你爲什麼不能從列表中刪除,如果'DataPoint'是一個自定義類,你需要實現'equals'和'hashCode'方法來使用'List.remove'。如果你使用Eclipse,這很容易:打開DataPoint類並右鍵單擊源窗口 - >源代碼 - >生成hashCode()和equals()。 Android的工作室是類似的:右源窗口 - >生成 - > equals()和hashCode() 希望幫助! –

2

從您的代碼中,我可以看到您的適配器由dplist填充。當您使用db.deleteRowByKey(dp);刪除一行時,您正在更新數據庫,但未更新dplist

您需要重新填充dplist才能與數據庫匹配,只有這樣notifyDataSetChanged()才能按預期工作。

一個簡單的方法來做到這將是您的refreshList()功能更改爲:

public void refreshList() 
{ 
    //reload dpList so that it can sync up with the database 
    dpList = db.allDataThisMonth(); 

    //now notify adapter that the data set has changed so that it can update itself. 
    adapter.notifyDataSetChanged(); 
} 
+0

謝謝!我必須將你的解決方案與亞當關於誇大新觀點的評論結合起來。 – Mike