ตัวอย่าง informDataSetChanged


166

ฉันพยายามที่จะใช้วิธีAndroid ApplicationการของฉันnotifyDataSetChanged()สำหรับArrayAdapterแต่มันไม่ทำงาน

ฉันพบว่าเป็นคำตอบที่นี่ที่notifyDataSetChanged()ควรทำงานในเธรดหลัก แต่ไม่มีตัวอย่างสำหรับที่

ใครช่วยส่งตัวอย่างหรืออย่างน้อยลิงค์?!



คุณสามารถตรวจสอบบล็อกนี้และตัวอย่างนี้ใน githubและสิ่งนี้ด้วย
Cabezas

คำตอบ:


328

สำหรับArrayAdapter, notifyDataSetChangedทำงานเฉพาะถ้าคุณใช้add(), insert(), remove()และclear()บนอะแดปเตอร์

เมื่อArrayAdapterมีการก่อสร้างก็ถืออ้างอิงสำหรับการListที่ถูกส่งผ่านใน. หากคุณกำลังจะผ่านในListที่เป็นสมาชิกของกิจกรรมและการเปลี่ยนแปลงสมาชิกกิจกรรมที่ต่อมาจะยังคงถืออ้างอิงไปที่เดิมArrayAdapter Listอะแดปเตอร์ไม่ทราบว่าคุณได้เปลี่ยนแปลงListกิจกรรม

ทางเลือกของคุณคือ:

  1. ใช้ฟังก์ชั่นของArrayAdapterการปรับเปลี่ยนรายการพื้นฐาน ( add(), insert(), remove(), clear()ฯลฯ )
  2. สร้างArrayAdapterใหม่Listด้วยข้อมูลใหม่ (ใช้ทรัพยากรจำนวนมากและการรวบรวมขยะ)
  3. สร้างคลาสของคุณเองมาจากBaseAdapterและListAdapterที่อนุญาตให้เปลี่ยนListโครงสร้างข้อมูลพื้นฐาน
  4. ใช้notifyDataSetChanged()ทุกครั้งที่มีการอัพเดตรายการ จะเรียกมันว่าใน UI-กระทู้ใช้ของrunOnUiThread() Activityจากนั้นnotifyDataSetChanged()จะทำงาน

13
ระวังเช่นกันในการกำหนดวัตถุ 'ใหม่' ให้กับข้อมูลของคุณ ใช้ clear () แทน repopulate / เปลี่ยนแปลงข้อมูลจากนั้นโทรแจ้งข้อมูล DataSetChanged ()
moonlightcheese

แต่สิ่งที่ถ้าเราเรียกnotifyDataSetChanged()ในลักษณะดังกล่าว((BaseAdapter) arrayAdapter).notifyDataSetChanged();?
teoREtik

2
ฉันใช้ Base ขยายableAdapterมันไม่มีฟังก์ชั่นเพิ่ม () หรือลบ () ดังนั้นฉันจึงเก็บแผนที่ของฉันเป็นตัวแปรสมาชิก ฉันอัปเดตแผนที่และโทรแจ้งเตือน DatasetChanged () แต่ไม่มีอะไรเกิดขึ้น เมื่อฉันใช้ตัวเลือก # 4 มันใช้งานได้ ทำไม???
emeraldhieu

ฉันใช้ ArrayAdapter สำหรับ GridView ที่กำหนดเองฉันกำลังเพิ่มรูปภาพเมื่อรับจาก url โดยการเรียก adapter.add (dataReceived) วิธีนี้ใช้งานได้ดีเพิ่มข้อมูล แต่ทำไมการรีเฟรชและไปด้านบน ฉันต้องการแสดงรายการเนื่องจากจะได้รับการเพิ่มโดยไม่มีรายการรีเฟรช (สิ่งที่ต้องการทำคือทำงานกับ GridView ของ android โดยใช้ informDatasetChanged ()) ฉันจะทำให้มันทำงานใน customGridView นี้ได้อย่างไร (StaggeredGridView)
MobileEvangelist

1
ฉันพยายามสร้าง BaseAdapter ของตัวเองเพื่อเพิ่มวิธีการเรียงลำดับลงในรายการ แต่ด้วยเหตุผลบางอย่างมันก็ไม่ทำงาน ไม่ว่าแอพของฉันจะช้าแม้ว่าฉันจะสร้างอะแดปเตอร์ทั้งหมดใหม่ด้วย arraylist เรียง แต่มันก็ยังทำให้ฉันรำคาญ มันจะสร้างขยะได้มากแค่ไหนกันแน่? ฉันถือว่าข้อมูลที่มีค่าใช้จ่ายจริงถูกเก็บไว้เป็นข้อมูลอ้างอิงในกิจกรรมที่เรียกใช้อะแด็ปเตอร์ซึ่งหมายถึงเฉพาะอะแดปเตอร์เท่านั้นที่จะถูกรวบรวม
G_V

34

คุณสามารถใช้runOnUiThread()วิธีการดังต่อไปนี้ หากคุณไม่ได้ใช้เพียงแค่ปรับตัวเข้ากับรหัสที่จะได้รับการอ้างอิงถึงคุณListActivityArrayAdapter

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

1
ฉันพยายามเพิ่มส่วนรหัสของคุณในรหัสของฉัน (คุณสามารถค้นหาได้ที่นี่stackoverflow.com/questions/3667442/how-to-refresh-adapter ) ใน onCreate-method แต่ฉันก็ยังไม่ประสบความสำเร็จ :( อาจจะผิดที่จะเพิ่มหรือไม่!
Tima

1
คำถามของคุณเพิ่งถามว่าคุณจะสามารถเรียกวิธีการนั้นได้อย่างไรและให้มันทำงานในเธรด UI หลัก คำถามนี้ตอบคำถามนี้ ในกรณีเฉพาะของคุณ ( stackoverflow.com/questions/3670500/ … ) AsyncTask และวิธี onPostExecute () ของมันดูเหมือนจะเป็นสิ่งที่คุณควรพิจารณา
Brian

12

ฉันเพิ่งเขียนในหัวข้อนี้แม้ว่าโพสต์นี้จะเก่าฉันคิดว่ามันจะเป็นประโยชน์กับคนที่ต้องการทราบวิธีการใช้BaseAdapter.notifyDataSetChanged()ขั้นตอนและในวิธีที่ถูกต้อง

โปรดปฏิบัติตามวิธีการใช้อย่างถูกต้อง BaseAdapter.notifyDataSetChanged () ใน Androidหรือบล็อกใหม่ BaseAdapter.notifyDataSetChanged ()


สวัสดีฉันลองตัวอย่างลิงค์แรก แต่แทนที่จะmItem.add()ทำฉันแก้ไขเพียงหนึ่งองค์ประกอบหมายความว่าmItem.get(position).setImage(encodedImage)อาจเป็นเพราะเหตุใดจึงให้ข้อผิดพลาด NullPointer exeption.So ไม่ทำงานแจ้งเตือน DataSetChange ทำงานเพียงแก้ไขมัน bcz สำหรับอะแดปเตอร์ Array มันดังกล่าวข้างต้นมันทำงาน เฉพาะสำหรับการเพิ่ม (), ล้าง (), ลบ () ฯลฯ
Shreekant N

AlertDataSetChanged จะทำงานเพื่อแก้ไขหรือแก้ไขชุดข้อมูลตัวชี้โมฆะของคุณเป็นอย่างอื่นตรวจสอบบันทึก
Arif Nadeem

7

ฉันมีปัญหาเดียวกันและฉันไม่ต้องการแทนที่ ArrayAdapter ทั้งหมดด้วยอินสแตนซ์ใหม่อย่างต่อเนื่อง ดังนั้นฉันจึงมี AdapterHelper ทำการยกของหนักที่อื่น

เพิ่มที่นี่ตามปกติที่คุณต้องการ (ลอง) โทรแจ้งเตือน

new AdapterHelper().update((ArrayAdapter)adapter, new ArrayList<Object>(yourArrayList));
adapter.notifyDataSetChanged();

คลาส AdapterHelper

public class AdapterHelper {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void update(ArrayAdapter arrayAdapter, ArrayList<Object> listOfObject){
        arrayAdapter.clear();
        for (Object object : listOfObject){
            arrayAdapter.add(object);
        }
    }
}

ฉันมี ArrayAdapters สองสามตัวในรหัสของฉันและพวกเขาก็ทำงานได้โดยไม่มีปัญหา คืนนี้ฉันตัดสินใจเปลี่ยน SimpleCursorAdapter เป็น ArrayAdapter และมันจะไม่ทำงาน หลังจากดิ้นรนกับมันสองสามชั่วโมงและพยายามหาเหตุผลว่าทำไมมันถึงใช้งานไม่ได้ฉันพบคลาสอะแดปเตอร์เฮลเพอร์ของคุณและตอนนี้มันก็ได้ผล! ขอบคุณ!
proudgeekdad

1
สิ่งนี้สามารถทำได้อย่างง่ายดายในฟังก์ชั่น ... ทำไมคุณยกตัวอย่างคลาสใหม่สำหรับมัน?
techiServices

2
ในฟังก์ชั่นจาวาเรียกว่าเมธอด สิ่งที่คุณจะเสนอให้มีวิธีการนี้ใช้งานได้สูงในชั้นเดียวกับอะแดปเตอร์ Array บางที หรือแฟรกเมนต์ / กิจกรรมที่มีมุมมองรายการ? ใช่แล้วมันอยู่ในคลาสที่สามารถนำกลับมาใช้ใหม่ได้ หากคุณต้องการทำให้มันคงที่โดยวิธีการทั้งหมดไปข้างหน้า
Kevin Parker

1
ความคิดดี. อีกอันหนึ่งก็คือการขยาย ArrayAdapter ชื่อ ArrayAdapterCompat และแทนที่เมธอด addAll (.. ) เนื่องจากอันนี้ใช้ได้ตั้งแต่ API 11 เท่านั้นในนั้นให้ตรวจสอบระดับ API และใช้super.addAll(..)สำหรับ API> 11 และ super.add (.. ) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }ร่วมกับการทำซ้ำเช่นคุณ: ตอนนี้เพิ่งขยายจากคลาสอะแดปเตอร์ใหม่ของคุณ
Konsumierer

ที่สมบูรณ์แบบ! ขอบคุณ @Kevin มาก - นี่คือสิ่งที่ฉันต้องการ!
Kibi

3

ฉันรู้ว่านี่เป็นการตอบสนองช้า แต่ฉันกำลังเผชิญปัญหาที่คล้ายกันและฉันจัดการเพื่อแก้ปัญหาโดยใช้notifyDataSetChanged()ในสถานที่ที่เหมาะสม

ดังนั้นสถานการณ์ของฉันเป็นดังนี้

ฉันต้องอัปเดตมุมมองในแท็บแถบการกระทำ (ส่วน) ด้วยเนื้อหาที่ส่งคืนจากกิจกรรมที่แตกต่างอย่างสิ้นเชิง อย่างไรก็ตามในขั้นต้น listview จะไม่แสดงการเปลี่ยนแปลงใด ๆ อย่างไรก็ตามเมื่อฉันคลิกที่แท็บอื่นแล้วกลับไปที่แท็บที่ต้องการ listview จะถูกอัพเดตด้วยเนื้อหาที่ถูกต้องจากกิจกรรมอื่น ดังนั้นเพื่อแก้ปัญหานี้ฉันใช้notifyDataSetChanged()อะแดปเตอร์แถบการกระทำในรหัสของกิจกรรมที่ต้องส่งคืนข้อมูล

นี่คือข้อมูลโค้ดที่ฉันใช้ในกิจกรรม

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) 
    {
        case R.id.action_new_forward:

            FragmentTab2.mListAdapter.notifyDataSetChanged();//this updates the adapter in my action bar tab
            Intent ina = new Intent(getApplicationContext(), MainActivity.class);
            ina.putExtra("stra", values1);
            startActivity(ina);// This is the code to start the parent activity of my action bar tab(fragment).
    }
}

กิจกรรมนี้จะกลับมาข้อมูลบางส่วนไปFragmentTab2และมันโดยตรงจะ update ListView FragmentTab2ของฉันใน

หวังว่าใครบางคนพบว่ามีประโยชน์นี้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.