จะรีเฟรช Android ListView
หลังจากเพิ่ม / ลบข้อมูลไดนามิกได้อย่างไร
จะรีเฟรช Android ListView
หลังจากเพิ่ม / ลบข้อมูลไดนามิกได้อย่างไร
คำตอบ:
โทรหาวัตถุnotifyDataSetChanged()
ของคุณAdapter
เมื่อคุณแก้ไขข้อมูลในอะแดปเตอร์นั้น
ข้อมูลจำเพาะเพิ่มเติมบางประการเกี่ยวกับวิธีการ / เวลาในการโทรnotifyDataSetChanged()
สามารถดูได้ในวิดีโอ Google I / Oนี้
นอกจากนี้คุณสามารถใช้สิ่งนี้:
myListView.invalidateViews();
invalidateViews()
ในชุดรหัสที่มาmDataChanged = true;
ดังนั้นผมไม่แน่ใจว่าถ้าผลในประสิทธิภาพที่ดีขึ้นเมื่อเทียบกับnotifyDataSetChanged()
invalidate()
, invalidateViews()
, requestLayout()
... คำตอบของคำถามนี้สิ่งที่ถูกต้องที่จะทำ (และโชคดีที่ยังมีการทำเครื่องหมายเป็นคำตอบที่เหมาะสม) เป็นที่จะเรียกnotifyDataSetChanged()
ในอะแดปเตอร์ของคุณ
หากการโทรnotifyDataSetChanged()
ไม่ทำงานวิธีการจัดวางทั้งหมดจะไม่ช่วยได้เช่นกัน เชื่อฉันListView
ได้รับการปรับปรุงอย่างถูกต้อง หากคุณไม่พบความแตกต่างคุณต้องตรวจสอบว่าข้อมูลในอะแดปเตอร์ของคุณมาจากที่ใด
ถ้านี่เป็นเพียงการเก็บรวบรวมรักษาคุณกำลังในการตรวจสอบหน่วยความจำที่คุณลบจริงหรือเพิ่มรายการ (s) notifyDataSetChanged()
เพื่อการเก็บรวบรวมก่อนที่จะเรียก
หากคุณกำลังทำงานกับฐานข้อมูลหรือบริการแบ็กเอนด์ที่คุณจะต้องโทรหาวิธีการที่จะดึงข้อมูลใหม่อีกครั้ง (หรือจัดการในข้อมูลหน่วยความจำ) notifyDataSetChanged()
ก่อนที่จะเรียก
สิ่งนี้notifyDataSetChanged
ใช้งานได้ก็ต่อเมื่อชุดข้อมูลมีการเปลี่ยนแปลง นั่นคือสถานที่ที่จะดูว่าคุณไม่พบการเปลี่ยนแปลงที่กำลังเกิดขึ้น แก้ไขข้อบกพร่องหากจำเป็น
ฉันพบว่าการทำงานกับอะแดปเตอร์ที่ช่วยให้คุณจัดการคอลเลกชันเช่น BaseAdapter ทำงานได้ดีขึ้น อะแดปเตอร์บางตัวเช่น ArrayAdapter นั้นจัดการคอลเลกชันของตัวเองอยู่แล้วทำให้ยากที่จะไปที่คอลเลกชันที่เหมาะสมสำหรับการอัพเดต จริงๆแล้วมันเป็นเพียงแค่เลเยอร์พิเศษที่ไม่มีความจำเป็นในกรณีส่วนใหญ่
เป็นความจริงที่ต้องเรียกใช้จากเธรด UI คำตอบอื่น ๆ มีตัวอย่างเกี่ยวกับวิธีการบรรลุเป้าหมาย อย่างไรก็ตามสิ่งนี้จำเป็นเฉพาะเมื่อคุณกำลังทำงานกับข้อมูลนี้จากนอกเธรด UI นั่นคือจากบริการหรือเธรด UI ที่ไม่ใช่ ในกรณีง่ายๆคุณจะอัปเดตข้อมูลของคุณจากการคลิกปุ่มหรือกิจกรรม / ส่วนอื่น ดังนั้นจึงยังคงอยู่ภายในเธรด UI ไม่จำเป็นต้องป๊อปที่ runOnUiTrhead อยู่เสมอ
สามารถพบได้ที่https://github.com/hanscappelle/so-2250770.git เพียงโคลนและเปิดโครงการใน Android Studio (gradle) โครงการนี้มีอาคารหลักที่ListView
มีข้อมูลสุ่มทั้งหมด รายการนี้สามารถรีเฟรชได้โดยใช้เมนูการกระทำ
การปรับใช้อะแด็ปเตอร์ที่ฉันสร้างขึ้นสำหรับตัวอย่างนี้ ModelObject จะเปิดเผยการรวบรวมข้อมูล
public class MyListAdapter extends BaseAdapter {
/**
* this is our own collection of data, can be anything we
* want it to be as long as we get the abstract methods
* implemented using this data and work on this data
* (see getter) you should be fine
*/
private List<ModelObject> mData;
/**
* our ctor for this adapter, we'll accept all the things
* we need here
*
* @param mData
*/
public MyListAdapter(final Context context, final List<ModelObject> mData) {
this.mData = mData;
this.mContext = context;
}
public List<ModelObject> getData() {
return mData;
}
// implement all abstract methods here
}
รหัสจาก MainActivity
public class MainActivity extends Activity {
private MyListAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView list = (ListView) findViewById(R.id.list);
// create some dummy data here
List<ModelObject> objects = getRandomData();
// and put it into an adapter for the list
mAdapter = new MyListAdapter(this, objects);
list.setAdapter(mAdapter);
// mAdapter is available in the helper methods below and the
// data will be updated based on action menu interactions
// you could also keep the reference to the android ListView
// object instead and use the {@link ListView#getAdapter()}
// method instead. However you would have to cast that adapter
// to your own instance every time
}
/**
* helper to show what happens when all data is new
*/
private void reloadAllData(){
// get new modified random data
List<ModelObject> objects = getRandomData();
// update data in our adapter
mAdapter.getData().clear();
mAdapter.getData().addAll(objects);
// fire the event
mAdapter.notifyDataSetChanged();
}
/**
* helper to show how only changing properties of data
* elements also works
*/
private void scrambleChecked(){
Random random = new Random();
// update data in our adapter, iterate all objects and
// resetting the checked option
for( ModelObject mo : mAdapter.getData()) {
mo.setChecked(random.nextBoolean());
}
// fire the event
mAdapter.notifyDataSetChanged();
}
}
อีกโพสต์ที่ดีเกี่ยวกับพลังของ listViews อยู่ที่นี่: http://www.vogella.com/articles/AndroidListView/article.html
adapter.clear()
และadapter.addAll(Array<T>)
ก่อนที่จะโทรnotifyDataSetChanged()
โทรหา runnable ได้ทุกเมื่อที่คุณต้องการ:
runOnUiThread(run);
OnCreate()
คุณตั้งค่าเธรดที่รันได้ของคุณ:
run = new Runnable() {
public void run() {
//reload content
arraylist.clear();
arraylist.addAll(db.readAll());
adapter.notifyDataSetChanged();
listview.invalidateViews();
listview.refreshDrawableState();
}
};
runOnUiThread()
ฟังก์ชั่น
run = new Runnable()
และเพิ่งให้ฟังก์ชั่นของฉันเป็นpublic void refreshUIThread()
วิธีที่เป็นแบบจำลองrun()
วิธีการของคุณ(ซึ่งก็ใช้ได้เช่นกัน)
ฉันมีปัญหากับการรีเฟรชมุมมองรายการแบบไดนามิก
โทรแจ้งข้อมูล DataSetChanged () ที่อแด็ปเตอร์ของคุณ
ข้อมูลเฉพาะเพิ่มเติมบางอย่างเกี่ยวกับวิธี / เวลาในการโทรแจ้งเตือน DataSetChanged () สามารถดูได้ในวิดีโอ Google I / O นี้
INFORMDataSetChanged () ทำงานไม่ถูกต้องในกรณีของฉัน [ฉันเรียกว่า NOTEDataSetChanged จากคลาสอื่น] ในกรณีที่ฉันแก้ไข ListView ในการทำงานกิจกรรม (Thread) วิดีโอนั้นต้องขอบคุณคริสโตเฟอร์ที่ให้คำแนะนำสุดท้าย
ในชั้นสองของฉันฉันใช้
Runnable run = new Runnable(){
public void run(){
contactsActivity.update();
}
};
contactsActivity.runOnUiThread(run);
เพื่อ acces การปรับปรุง () จากกิจกรรมของฉัน การอัปเดตนี้รวมถึง
myAdapter.notifyDataSetChanged();
เพื่อบอกให้อะแด็ปเตอร์รีเฟรชมุมมอง ทำงานได้ดีเท่าที่ฉันสามารถพูดได้
หากคุณกำลังใช้SimpleCursorAdapterให้ลองเรียกสอบถามใหม่()กับวัตถุเคอร์เซอร์
หากคุณยังไม่พอใจกับ ListView Refreshment คุณสามารถดูตัวอย่างนี้สำหรับการโหลด listView จาก DB ที่จริงสิ่งที่คุณต้องทำคือเพียงแค่โหลด ListView อีกครั้งหลังจากที่คุณดำเนินการ CRUD มันไม่ใช่วิธีที่ดีที่สุดในการ รหัส แต่มันจะรีเฟรช ListView ตามที่คุณต้องการ ..
มันเหมาะกับฉัน .... ถ้าหากคุณพบทางออกที่ดีกว่าโปรดแชร์ ...
....... ...... ดำเนินการ CRUD ของคุณ .. ...... ..... DBAdapter.open (); DBAdapter.insert_into_SingleList (); // นำ DB_results นั้นมาและเพิ่มลงในรายการเป็นเนื้อหา ... ls2.setAdapter (ใหม่ ArrayAdapter (DynTABSample.this android.R.layout.simple_list_item_1, DBAdapter.DB_ListView)); DBAdapter.close ();
โซลูชันที่เสนอโดยบุคคลในโพสต์นี้ใช้งานได้หรือไม่ขึ้นอยู่กับรุ่น Android ของอุปกรณ์ของคุณเป็นหลัก ตัวอย่างเช่นการใช้วิธี AddAll คุณต้องใส่ android: minSdkVersion = "10" ในอุปกรณ์ android ของคุณ
เพื่อแก้คำถามนี้สำหรับอุปกรณ์ทั้งหมดที่ฉันได้สร้างวิธีการของตัวเองในอะแดปเตอร์ของฉันและใช้ในการเพิ่มและลบวิธีการสืบทอดจาก ArrayAdapter ที่ปรับปรุงข้อมูลของคุณโดยไม่มีปัญหา
รหัสของฉัน: การใช้คลาสข้อมูลของฉันเอง RaceResult คุณใช้โมเดลข้อมูลของคุณเอง
ResultGpRowAdapter.java
public class ResultGpRowAdapter extends ArrayAdapter<RaceResult> {
Context context;
int resource;
List<RaceResult> data=null;
public ResultGpRowAdapter(Context context, int resource, List<RaceResult> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.data = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
........
}
//my own method to populate data
public void myAddAll(List<RaceResult> items) {
for (RaceResult item:items){
super.add(item);
}
}
ResultsGp.java
public class ResultsGp extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
...........
...........
ListView list = (ListView)findViewById(R.id.resultsGpList);
ResultGpRowAdapter adapter = new ResultGpRowAdapter(this, R.layout.activity_result_gp_row, new ArrayList<RaceResult>()); //Empty data
list.setAdapter(adapter);
....
....
....
//LOAD a ArrayList<RaceResult> with data
ArrayList<RaceResult> data = new ArrayList<RaceResult>();
data.add(new RaceResult(....));
data.add(new RaceResult(....));
.......
adapter.myAddAll(data); //Your list will be udpdated!!!
หากคุณต้องการรักษาตำแหน่งการเลื่อนเมื่อรีเฟรชและคุณสามารถทำได้:
if (mEventListView.getAdapter() == null) {
EventLogAdapter eventLogAdapter = new EventLogAdapter(mContext, events);
mEventListView.setAdapter(eventLogAdapter);
} else {
((EventLogAdapter)mEventListView.getAdapter()).refill(events);
}
public void refill(List<EventLog> events) {
mEvents.clear();
mEvents.addAll(events);
notifyDataSetChanged();
}
สำหรับข้อมูลรายละเอียดโปรดดูAndroid ListView: รักษาเลื่อนตำแหน่งของคุณเมื่อคุณรีเฟรช
เพียงใช้myArrayList.remove(position);
ภายในฟัง:
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
myArrayList.remove(position);
myArrayAdapter.notifyDataSetChanged();
}
});
คุณจำเป็นต้องใช้วัตถุเดียวของรายการว่าข้อมูล whoose ListView
คุณกำลังพองบน หากการอ้างอิงคือการเปลี่ยนแปลงก็ใช้ notifyDataSetChanged()
งานไม่ได้เมื่อใดก็ตามที่คุณลบองค์ประกอบจากมุมมองรายการให้ลบองค์ประกอบเหล่านั้นออกจากรายการที่คุณใช้ไม่ว่าจะเป็น ArrayList <> หรืออย่างอื่นจากนั้นเรียก
notifyDataSetChanged()
ใช้วัตถุของคลาสอะแดปเตอร์ของคุณ
ดังนั้นที่นี่ดูว่าฉันจัดการมันในอะแดปเตอร์ของฉันดูด้านล่าง
public class CountryCodeListAdapter extends BaseAdapter implements OnItemClickListener{
private Context context;
private ArrayList<CountryDataObject> dObj;
private ViewHolder holder;
private Typeface itemFont;
private int selectedPosition=-1;
private ArrayList<CountryDataObject> completeList;
public CountryCodeListAdapter(Context context, ArrayList<CountryDataObject> dObj) {
this.context = context;
this.dObj=dObj;
completeList=new ArrayList<CountryDataObject>();
completeList.addAll(dObj);
itemFont=Typeface.createFromAsset(context.getAssets(), "CaviarDreams.ttf");
}
@Override
public int getCount() {
return dObj.size();
}
@Override
public Object getItem(int position) {
return dObj.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
if(view==null){
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.states_inflator_layout, null);
holder.textView = ((TextView)view.findViewById(R.id.stateNameInflator));
holder.checkImg=(ImageView)view.findViewById(R.id.checkBoxState);
view.setTag(holder);
}else{
holder = (ViewHolder) view.getTag();
}
holder.textView.setText(dObj.get(position).getCountryName());
holder.textView.setTypeface(itemFont);
if(position==selectedPosition)
{
holder.checkImg.setImageResource(R.drawable.check);
}
else
{
holder.checkImg.setImageResource(R.drawable.uncheck);
}
return view;
}
private class ViewHolder{
private TextView textView;
private ImageView checkImg;
}
public void getFilter(String name) {
dObj.clear();
if(!name.equals("")){
for (CountryDataObject item : completeList) {
if(item.getCountryName().toLowerCase().startsWith(name.toLowerCase(),0)){
dObj.add(item);
}
}
}
else {
dObj.addAll(completeList);
}
selectedPosition=-1;
notifyDataSetChanged();
notifyDataSetInvalidated();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Registration reg=(Registration)context;
selectedPosition=position;
reg.setSelectedCountryCode("+"+dObj.get(position).getCountryCode());
notifyDataSetChanged();
}
}
refreshDrawableState()
หลังจากลบข้อมูลจากมุมมองรายการคุณต้องโทร นี่คือตัวอย่าง:
final DatabaseHelper db = new DatabaseHelper (ActivityName.this);
db.open();
db.deleteContact(arg3);
mListView.refreshDrawableState();
db.close();
และdeleteContact
วิธีการในDatabaseHelper
ชั้นเรียนจะมีลักษณะค่อนข้าง
public boolean deleteContact(long rowId) {
return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0;
}
ฉันไม่สามารถรับ informDataSetChanged () เพื่ออัปเดต SimpleAdapter ของฉันได้ดังนั้นฉันจึงลองลบมุมมองทั้งหมดที่แนบกับโครงร่างหลักโดยใช้ removeAllViews () จากนั้นเพิ่ม ListView และใช้งานได้ช่วยให้ฉันอัปเดต UI:
LinearLayout results = (LinearLayout)findViewById(R.id.results);
ListView lv = new ListView(this);
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row,
new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } );
for (...) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", name);
map.put("dept", dept);
list.add(map);
}
lv.setAdapter(adapter);
results.removeAllViews();
results.addView(lv);
สำหรับฉันหลังจากการเปลี่ยนแปลงข้อมูลในฐานข้อมูล sql ไม่มีอะไรที่สามารถรีเฟรชมุมมองรายการ (เป็นมุมมองรายการแบบขยายได้) ดังนั้นถ้า informDataSetChanged () ไม่ช่วยคุณสามารถลองล้างรายการของคุณก่อนและเพิ่มอีกครั้งหลังจากการโทร ตัวอย่างเช่น
private List<List<SomeNewArray>> arrayList;
List<SomeNewArray> array1= getArrayList(...);
List<SomeNewArray> array2= getArrayList(...);
arrayList.clear();
arrayList.add(array1);
arrayList.add(array2);
notifyDataSetChanged();
หวังว่ามันสมเหตุสมผลสำหรับคุณ
ในขณะที่ใช้ SimpleCursorAdapter สามารถเรียก changeCursor (newCursor) บนอะแดปเตอร์
ฉันก็เหมือนกันเมื่อในส่วนฉันต้องการเติม ListView (ใน TextView เดียว) ด้วยที่อยู่ mac ของอุปกรณ์ BLE ที่สแกนในบางครั้ง
สิ่งที่ฉันทำคือ:
public class Fragment01 extends android.support.v4.app.Fragment implements ...
{
private ListView listView;
private ArrayAdapter<String> arrayAdapter_string;
...
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
...
this.listView= (ListView) super.getActivity().findViewById(R.id.fragment01_listView);
...
this.arrayAdapter_string= new ArrayAdapter<String>(super.getActivity(), R.layout.dispositivo_ble_item, R.id.fragment01_item_textView_titulo);
this.listView.setAdapter(this.arrayAdapter_string);
}
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
...
super.getActivity().runOnUiThread(new RefreshListView(device));
}
private class RefreshListView implements Runnable
{
private BluetoothDevice bluetoothDevice;
public RefreshListView(BluetoothDevice bluetoothDevice)
{
this.bluetoothDevice= bluetoothDevice;
}
@Override
public void run()
{
Fragment01.this.arrayAdapter_string.add(new String(bluetoothDevice.toString()));
Fragment01.this.arrayAdapter_string.notifyDataSetChanged();
}
}
จากนั้น ListView จะเริ่มเติมข้อมูลแบบไดนามิกด้วยที่อยู่ mac ของอุปกรณ์ที่พบ
ฉันคิดว่ามันขึ้นอยู่กับความหมายของการรีเฟรช คุณหมายถึงว่าการแสดงผล GUI ควรมีการรีเฟรชหรือคุณหมายความว่ามุมมองลูกควรได้รับการรีเฟรชซึ่งคุณสามารถเรียกใช้ getChildAt (int) แบบเป็นโปรแกรมและรับมุมมองที่สอดคล้องกับสิ่งที่อยู่ในอะแดปเตอร์
หากคุณต้องการให้จอแสดงผล GUI รีเฟรชให้โทรแจ้งให้ทราบ DataSetChanged () บนอแด็ปเตอร์ GUI จะรีเฟรชเมื่อวาดใหม่ในครั้งถัดไป
หากคุณต้องการเรียกใช้ getChildAt (int) และรับมุมมองที่สะท้อนถึงสิ่งที่อยู่ในอะแดปเตอร์ให้โทรไปที่ layoutChildren () นี่จะทำให้มุมมองลูกถูกสร้างขึ้นใหม่จากข้อมูลอะแดปเตอร์
ฉันมี ArrayList ที่ฉันต้องการแสดงใน listview ArrayList มีองค์ประกอบจาก mysql ฉันลบล้างวิธี onRefresh และในวิธีนั้นฉันใช้tablelayout.removeAllViews (); จากนั้นทำซ้ำกระบวนการรับข้อมูลอีกครั้งจากฐานข้อมูล แต่ก่อนหน้านั้นอย่าลืมล้าง ArrayList ของคุณหรือโครงสร้างข้อมูลใด ๆ มิฉะนั้นข้อมูลใหม่จะถูกผนวกเข้ากับอันเก่า
หากคุณต้องการอัปเดต UI listview จากบริการให้ทำอะแดปเตอร์ให้คงที่ในกิจกรรมหลักของคุณและทำสิ่งนี้:
@Override
public void onDestroy() {
if (MainActivity.isInFront == true) {
if (MainActivity.adapter != null) {
MainActivity.adapter.notifyDataSetChanged();
}
MainActivity.listView.setAdapter(MainActivity.adapter);
}
}
หากคุณกำลังจะไปโดยเส้นคู่มือ Android และคุณกำลังใช้ContentProviders
เพื่อรับข้อมูลจากDatabase
และคุณจะแสดงในการListView
ใช้CursorLoader
และCursorAdapters
จากนั้นการเปลี่ยนแปลงทั้งหมดของคุณข้อมูลที่เกี่ยวข้องจะปรากฏใน ListView โดยอัตโนมัติ
getContext().getContentResolver().notifyChange(uri, null);
เคอร์เซอร์ของคุณในContentProvider
จะเพียงพอที่จะสะท้อนการเปลี่ยนแปลงไม่จำเป็นต้องมีการแก้ไขเพิ่มเติม
แต่เมื่อคุณไม่ได้ใช้สิ่งเหล่านี้คุณต้องบอกอะแดปเตอร์เมื่อชุดข้อมูลกำลังเปลี่ยนแปลง นอกจากนี้คุณต้องเติม / โหลดชุดข้อมูลของคุณอีกครั้ง (พูดรายการ) จากนั้นคุณต้องโทรหาnotifyDataSetChanged()
อะแดปเตอร์
notifyDataSetChanged()
จะไม่ทำงานหากไม่มีการเปลี่ยนแปลงในชุดข้อมูล นี่คือความคิดเห็นข้างต้นวิธีการในเอกสาร -
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
ฉันสามารถรับการแจ้งเตือน DataSetChanged ได้โดยการรับข้อมูลอะแดปเตอร์ใหม่เท่านั้นจากนั้นรีเซ็ตอะแดปเตอร์สำหรับมุมมองรายการจากนั้นทำการโทรออกดังนี้
expandableAdapter = baseFragmentParent.setupEXLVAdapter();
baseFragmentParent.setAdapter(expandableAdapter);
expandableAdapter.notifyDataSetChanged();
ในตัวเลือกอื่น ๆ เป็นonWindowFocusChanged
วิธีการ แต่แน่ใจว่ามันมีความละเอียดอ่อนและต้องการการเข้ารหัสพิเศษสำหรับผู้ที่สนใจ
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
// some controls needed
programList = usersDBHelper.readProgram(model.title!!)
notesAdapter = DailyAdapter(this, programList)
notesAdapter.notifyDataSetChanged()
listview_act_daily.adapter = notesAdapter
}
พิจารณาว่าคุณส่งรายการไปยังอะแดปเตอร์ของคุณแล้ว
ใช้:
list.getAdapter().notifyDataSetChanged()
เพื่ออัปเดตรายการของคุณ
ถ้าฉันพูดถึงสถานการณ์ของฉันที่นี่คำตอบที่ไม่ใช่คำตอบข้างต้นจะไม่ทำงานเพราะฉันมีกิจกรรมที่แสดงรายการของค่า db พร้อมกับปุ่มลบและเมื่อกดปุ่มลบฉันต้องการลบรายการนั้นออกจากรายการ
สิ่งที่น่าสนใจคือฉันไม่ได้ใช้มุมมองรีไซเคิล แต่เป็นลิสต์แบบง่ายและมุมมองลิสต์นั้นเริ่มต้นได้ในคลาสอะแด็ปเตอร์ ดังนั้นการเรียกnotifyDataSetChanged()
จะไม่ทำอะไรภายในคลาสอะแดปเตอร์และแม้แต่ในคลาสกิจกรรมที่วัตถุอะแดปเตอร์จะเริ่มต้นได้เนื่องจากวิธีการลบอยู่ในคลาสอะแดปเตอร์
ดังนั้นวิธีการคือการลบวัตถุออกจากอะแดปเตอร์ในgetView
วิธีการเรียนอะแดปเตอร์(เพื่อลบเฉพาะวัตถุนั้น แต่ถ้าคุณต้องการที่จะลบทั้งหมดโทรclear()
)
เพื่อให้คุณได้แนวคิดบางอย่างรหัสของฉันเป็นอย่างไร
public class WordAdapter extends ArrayAdapter<Word> {
Context context;
public WordAdapter(Activity context, ArrayList<Word> words) {}
//.......
@NonNull
@Override
public View getView(final int position, View convertView, ViewGroup group) {
//.......
ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
deleteBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (vocabDb.deleteWord(currentWord.id)) {
//.....
} else{
//.....
}
remove(getItem(position)); // <---- here is the trick ---<
//clear() // if you want to clear everything
}
});
//....
หมายเหตุ: ที่นี่remove()
และgetItem()
วิธีการที่สืบทอดมาจากชั้นอะแดปเตอร์
remove()
- เพื่อลบรายการเฉพาะที่คลิกgetItem(position)
- คือการรับไอเท็ม (ที่นี่นั่นคือวัตถุ Word ของฉันที่ฉันเพิ่มลงในรายการ) จากตำแหน่งที่คลิกนี่คือวิธีที่ฉันตั้งค่าอะแดปเตอร์เป็นลิสต์วิวในคลาสกิจกรรม
ArrayList<Word> wordList = new ArrayList();
WordAdapter adapter = new WordAdapter(this, wordList);
ListView list_view = (ListView) findViewById(R.id.activity_view_words);
list_view.setAdapter(adapter);