Làm thế nào để làm mới listview Android?


436

Làm cách nào để làm mới Android ListViewsau khi thêm / xóa dữ liệu động?


3
Nếu các giải pháp khác không hoạt động, hãy thử refreshDrawableState. Đạo cụ để stackoverflow.com/questions/5186359/ Mạnh
Edwin Evans


Một ví dụ ở đây guidekart.com/kotlin-android/ từ có thể giúp bạn.
Mallikar Quân M

Câu trả lời:


530

Gọi notifyDataSetChanged()cho Adapterđối tượng của bạn sau khi bạn đã sửa đổi dữ liệu trong bộ điều hợp đó.

Một số chi tiết cụ thể về cách thức / thời điểm gọi notifyDataSetChanged()có thể được xem trong video Google I / O này .


24
Bạn nên chạy nó trên luồng UI. Tạo một trình xử lý trong chuỗi UI và sau đó đăng Runable lên nó
Kirill Kulakov

11
Một lần nữa: notifyDataSetChanged () không hoạt động ít nhất là không sử dụng cho các hoạt động sử dụng được đề xuất (đọc không được phản đối). Nếu sử dụng listview, bộ điều hợp con trỏ và nhà cung cấp nội dung, bạn có thể thử một cái gì đó dọc theo dòng: gettLoaderManager (). RestartLoader (). Xem: stackoverflow.com/a/19657500/1087411 Tôi muốn xem ít nhất một số tài liệu về notifyDataSetChanged (). Để nhiều trong Android là để thử nghiệm hộp đen.
Anderson

Nếu thông báoDataSetChanged không hoạt động, bạn là người đã làm sai
zdarsky.peter

4
notifyDataSetChanged không phải lúc nào cũng hoạt động. Tôi không chắc tại sao điều này lại xảy ra. Đôi khi bạn phải gọi listView.setAdOG (bộ chuyển đổi) để xóa các khung nhìn cũ. Xem thêm: stackoverflow.com/a/16261588/153275

1
Tôi không bao giờ có thể làm cho notifyDataSetChanged hoạt động. Tôi có thể thấy rõ rằng bộ sưu tập tôi cung cấp cho bộ điều hợp đã thay đổi (các phần tử đã bị xóa) nhưng thông báoDataSetChanged chưa bao giờ làm gì cả. Không chắc chắn nếu phương pháp này chỉ bị hỏng?
tạm biệt

204

Ngoài ra, bạn có thể sử dụng này:

myListView.invalidateViews();

22
Đây là câu trả lời đúng nếu người ta chỉ cần GIẢM lại khung nhìn. Ví dụ: sau khi đăng nhập người dùng xảy ra cần hiển thị thêm thông tin hoặc tùy chọn trong mỗi chế độ xem của listView. Đó là những gì tôi cần làm, vì vậy đã bỏ phiếu. Nếu dữ liệu cơ bản thay đổi, có lẽ nên sử dụng notifyDataSetChanged ().
SBerg413

Trên thực tế, invalidateViews()trong bộ mã nguồn, mDataChanged = true;vì vậy tôi không chắc liệu điều này có mang lại hiệu suất tốt hơn so vớinotifyDataSetChanged()
vovahost

Bạn đã cứu ngày của tôi, anh bạn!
oskarko

bạn có thể lấy một loại danh sách là "danh sách có thể quan sát", không cần thay đổi thông báo
Priya

153

Hãy bỏ qua tất cả các invalidate(), invalidateViews(),requestLayout() , ... câu trả lời cho câu hỏi này.

Điều đúng đắn cần làm (và may mắn cũng được đánh dấu là câu trả lời đúng) là gọi notifyDataSetChanged()Bộ điều hợp của bạn .

Xử lý sự cố

Nếu gọi notifyDataSetChanged()không hoạt động, tất cả các phương pháp bố trí sẽ không giúp được gì. Tin tôi điListView đã được cập nhật đúng. Nếu bạn không tìm thấy sự khác biệt, bạn cần kiểm tra dữ liệu trong bộ điều hợp của bạn đến từ đâu.

Nếu đây chỉ là một bộ sưu tập bạn đang giữ trong bộ nhớ, hãy kiểm tra xem bạn thực sự đã xóa hoặc thêm (các) mục vào bộ sưu tập trước khi gọi notifyDataSetChanged().

Nếu bạn đang làm việc với cơ sở dữ liệu hoặc dịch vụ phụ trợ, bạn sẽ phải gọi phương thức để lấy lại thông tin (hoặc thao tác trong dữ liệu bộ nhớ) trước khi gọi notifyDataSetChanged().

Điều này notifyDataSetChangedchỉ hoạt động nếu bộ dữ liệu đã thay đổi. Vì vậy, đó là nơi để tìm nếu bạn không tìm thấy những thay đổi sắp tới. Gỡ lỗi nếu cần.

ArrayAd CHƯƠNG vs BaseAd CHƯƠNG

Tôi đã thấy rằng làm việc với một bộ chuyển đổi cho phép bạn quản lý bộ sưu tập, như BaseAd CHƯƠNG hoạt động tốt hơn. Một số bộ điều hợp như ArrayAd CHƯƠNG đã quản lý bộ sưu tập của riêng họ khiến việc tìm bộ sưu tập thích hợp để cập nhật trở nên khó khăn hơn. Nó thực sự chỉ là một lớp khó khăn thêm không cần thiết trong hầu hết các trường hợp.

Giao diện người dùng

Đúng là điều này phải được gọi từ luồng UI. Các câu trả lời khác có ví dụ về cách đạt được điều này. Tuy nhiên, điều này chỉ được yêu cầu nếu bạn đang làm việc với thông tin này từ bên ngoài luồng UI. Đó là từ một dịch vụ hoặc một chủ đề không phải UI. Trong những trường hợp đơn giản, bạn sẽ cập nhật dữ liệu của mình từ một lần bấm nút hoặc một hoạt động / đoạn khác. Vì vậy, vẫn trong chủ đề UI. Không cần phải luôn bật mà chạyOnUiTrhead.

Dự án ví dụ nhanh

Có thể được tìm thấy tại https://github.com/hanscappelle/so-2250770.git . Chỉ cần sao chép và mở dự án trong Android Studio (gradle). Dự án này có một tòa nhà chính.ListView với tất cả dữ liệu ngẫu nhiên. Danh sách này có thể được làm mới bằng cách sử dụng menu hành động.

Việc triển khai bộ điều hợp mà tôi đã tạo cho ví dụ này ModelObject hiển thị bộ sưu tập dữ liệu

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
}

Mã từ 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();
    }
}

Thêm thông tin

Một bài viết hay khác về sức mạnh của listViews được tìm thấy ở đây: http://www.vogella.com/articles/AndroidListView/article.html


16
Bạn sai rồi. notifyDataSetChanged () không hoạt động với tôi, nhưng không hợp lệViews () đã làm đúng.
babay

6
Tôi có vấn đề trong đó các yếu tố thực tế trong danh sách không thay đổi, ví dụ như cùng một lượng yếu tố. Nhưng vấn đề là cách chúng được trình bày cần phải thay đổi. Điều đó có nghĩa là mã bộ điều hợp của tôi để xây dựng giao diện người dùng cần chạy lại và sau đó ẩn chính xác một số phần tử trong các hàng danh sách. notifyDataSetChanged () không hoạt động ...
Sven Haiges

9
Câu trả lời này thực sự đã giúp tôi ra ngoài. Tôi đã giữ mảng trong bộ nhớ vì những lý do tính năng nhất định. Để khắc phục, bây giờ tôi gọi adapter.clear()adapter.addAll(Array<T>)trước khi gọinotifyDataSetChanged()
Michael DePhillips

2
@hcpl, tôi nên gọi notifyDataSetChanged như thế nào nếu tôi đang sử dụng OnClickListener cho bộ kiểm tra? defaultateViews đang hoàn thành công việc ngay bây giờ. Tại sao không hợp lệ Xem phương thức sai để gọi?
vươn

1
Tôi không bao giờ có thể làm cho notifyDataSetChanged hoạt động. Tôi có thể thấy rõ rằng bộ sưu tập tôi cung cấp cho bộ điều hợp đã thay đổi (các phần tử đã bị xóa) nhưng thông báoDataSetChanged chưa bao giờ làm gì cả. Không chắc chắn nếu phương pháp này chỉ bị hỏng?
tạm biệt

42

Gọi runnable bất cứ khi nào bạn muốn:

runOnUiThread(run);

OnCreate(), bạn đặt chủ đề có thể chạy của bạn:

run = new Runnable() {
    public void run() {
        //reload content
        arraylist.clear();
        arraylist.addAll(db.readAll());
        adapter.notifyDataSetChanged();
        listview.invalidateViews();
        listview.refreshDrawableState();
    }
};

1
Cũng hoạt động trong trường hợp của tôi, nơi tôi cần cập nhật một listview dựa trên dữ liệu đến từ kết nối TCP (từ luồng "nonUI"). Cách duy nhất để vẽ lại danh sách là xóa và thêm lại tất cả các phần tử của ArrayList. Dù sao, nếu bạn đã có trong giao diện người dùng, bạn không cần phải gọi mã thông qua runOnUiThread()chức năng.
Andre

Cảm ơn! Nó làm việc cho tôi. Đối với tất cả những người muốn chạy mã này từ một đoạn, bạn nên sử dụng getActivity (). RunOnUiThread (Runnable mới ... để đảm bảo mã được chạy trên luồng UI
mã hóa

Tôi không thấy mục đích của run = new Runnable()và chỉ cung cấp cho hàm của tôi một public void refreshUIThread()phương thức mô hình hóa run()phương thức của bạn (cũng hoạt động).
T.Woody

11

tôi có một số vấn đề với làm mới năng động của listview của tôi.

Gọi notifyDataSetChanged () trên Adaptor của bạn.

Một số thông tin cụ thể bổ sung về cách thức / thời điểm gọi notifyDataSetChanged () có thể được xem trong video Google I / O này.

notifyDataSetChanged () không hoạt động đúng trong trường hợp của tôi [Tôi đã gọi notifyDataSetChanged từ một lớp khác]. Chỉ trong trường hợp tôi đã chỉnh sửa ListView trong Activity (Thread) đang chạy. Video đó nhờ Christopher đã đưa ra gợi ý cuối cùng.

Trong lớp thứ hai của tôi, tôi đã sử dụng

Runnable run = new Runnable(){
     public void run(){
         contactsActivity.update();
     }
};
contactsActivity.runOnUiThread(run);

để truy cập cập nhật () từ Hoạt động của tôi. Bản cập nhật này bao gồm

myAdapter.notifyDataSetChanged();

để nói với Adaptor để làm mới khung nhìn. Làm việc tốt như tôi có thể nói.



5

nếu bạn vẫn chưa hài lòng với Làm mới ListView, bạn có thể xem đoạn mã này, đây là để tải listView từ DB, thực tế những gì bạn phải làm chỉ là tải lại ListView, sau khi bạn thực hiện bất kỳ Thao tác CRUD nào, đó không phải là cách tốt nhất để mã, nhưng nó sẽ làm mới ListView như bạn muốn ..

Nó hoạt động cho tôi .... nếu bạn tìm thấy giải pháp tốt hơn, vui lòng Chia sẻ ...

.......
......
thực hiện các hoạt động CRUD của bạn ..
......
.....
DBAd CHƯƠNG.open ();
DBAd CHƯƠNG.insert_into_SingleList ();
// Mang DB_results đó và thêm nó vào danh sách như nội dung của nó ....
                                            ls2.setAd CHƯƠNG (ArrayAd CHƯƠNG mới (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAd CHƯƠNG.DB_ListView));
                                            DBAd CHƯƠNG.c Đóng ();

2

Các giải pháp được đề xuất bởi những người trong bài đăng này hoạt động hay không chủ yếu phụ thuộc vào phiên bản Android của thiết bị của bạn. Ví dụ để sử dụng phương thức AddAll, bạn phải đặt android: minSdkVersion = "10" trong thiết bị Android của mình.

Để giải quyết câu hỏi này cho tất cả các thiết bị, tôi đã tự tạo phương thức của mình trong bộ điều hợp và sử dụng bên trong phương thức thêm và xóa từ ArrayAd CHƯƠNG để cập nhật dữ liệu cho bạn mà không gặp vấn đề gì.

Mã của tôi: Sử dụng lớp dữ liệu của riêng tôi RaceResult, bạn sử dụng mô hình dữ liệu của riêng bạn.

Kết quảGpRowAd Module.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);
        }
    }

Kết quảGp.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!!!

1

Nếu bạn muốn duy trì vị trí cuộn của mình khi bạn làm mới và bạn có thể làm điều này:

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();
}

Để biết thông tin chi tiết, vui lòng xem Android ListView: Duy trì vị trí cuộn của bạn khi bạn làm mới .


1

Chỉ cần sử dụng myArrayList.remove(position);bên trong một người nghe:

  myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
           myArrayList.remove(position);
           myArrayAdapter.notifyDataSetChanged();
        }
    });

1

Bạn cần sử dụng một đối tượng duy nhất của danh sách dữ liệu mà bạn đang lạm dụng ListView. Nếu tham chiếu là thay đổi thì không notifyDataSetChanged()hoạt động. Bất cứ khi nào bạn đang xóa các thành phần khỏi chế độ xem danh sách cũng sẽ xóa chúng khỏi danh sách bạn đang sử dụng cho dù đó là ArrayList <> hay Something khác sau đó Gọi notifyDataSetChanged()đối tượng của lớp Adaptor của bạn.

Vì vậy, ở đây xem làm thế nào tôi quản lý nó trong bộ chuyển đổi của tôi xem bên dưới

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();
}
}

1
lời giải thích của bạn bị đánh giá thấp, nhưng nó thực sự cho tôi hiểu về tham chiếu danh sách mảng. cảm ơn bạn
Abraham Putra Prakasa

0

Sau khi xóa dữ liệu khỏi chế độ xem danh sách, bạn phải gọi refreshDrawableState(). Dưới đây là ví dụ:

final DatabaseHelper db = new DatabaseHelper (ActivityName.this);

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

deleteContactphương thức trong DatabaseHelperlớp sẽ giống như

public boolean deleteContact(long rowId) {

   return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0;

}

0

Tôi đã không thể nhận được notifyDataSetChanged () để cập nhật SimpleAd CHƯƠNG của mình, vì vậy thay vào đó, trước tiên tôi đã thử xóa tất cả các chế độ xem được gắn vào bố cục cha mẹ bằng cách sử dụng removeAllViews (), sau đó thêm ListView và cho phép tôi cập nhật 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);

0

Đối với tôi sau khi thay đổi thông tin trong cơ sở dữ liệu sql, không có gì có thể làm mới chế độ xem danh sách (để được xem danh sách cụ thể có thể mở rộng), vì vậy, nếu notifyDataSetChanged () không giúp đỡ, bạn có thể thử xóa danh sách của mình trước và thêm lại sau khi cuộc gọi đó thông báoDataSetChanged (). Ví dụ

private List<List<SomeNewArray>> arrayList;
List<SomeNewArray> array1= getArrayList(...);
List<SomeNewArray> array2= getArrayList(...);
arrayList.clear();
arrayList.add(array1);
arrayList.add(array2);
notifyDataSetChanged();

Hy vọng nó có ý nghĩa cho bạn.


0

trong khi sử dụng SimpleC bổngAd CHƯƠNG có thể gọi changeCthon (newCthon) trên bộ điều hợp.


0

Tôi cũng như vậy khi, trong một đoạn, tôi muốn đưa vào một ListView (trong một TextView) với địa chỉ mac của các thiết bị BLE được quét trong một thời gian.

Những gì tôi đã làm là thế này:

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();
    }
}

Sau đó, ListView bắt đầu tự động điền địa chỉ mac của các thiết bị được tìm thấy.


0

Tôi nghĩ rằng nó phụ thuộc vào những gì bạn có nghĩa là làm mới. Bạn có nghĩa là màn hình GUI phải được làm mới, hay bạn có nghĩa là các khung nhìn con nên được làm mới để bạn có thể gọi getChildAt (int) theo chương trình và có được khung nhìn tương ứng với những gì có trong Adaptor.

Nếu bạn muốn màn hình GUI được làm mới, hãy gọi notifyDataSetChanged () trên bộ điều hợp. GUI sẽ được làm mới khi vẽ lại tiếp theo.

Nếu bạn muốn có thể gọi getChildAt (int) và có được một khung nhìn phản ánh những gì trong bộ điều hợp, hãy gọi đến layoutChildren (). Điều này sẽ khiến chế độ xem con được xây dựng lại từ dữ liệu bộ điều hợp.


0

Tôi đã có một ArrayList mà tôi muốn hiển thị trong một listview. ArrayList chứa các phần tử từ mysql. Tôi đã ghi đè phương thức onRefresh và trong phương thức đó tôi đã sử dụng tablelayout.removeAllViews (); và sau đó lặp lại quá trình lấy lại dữ liệu từ cơ sở dữ liệu. Nhưng trước đó, hãy đảm bảo xóa ArrayList của bạn hoặc bất kỳ cấu trúc dữ liệu nào hoặc dữ liệu mới khác sẽ được thêm vào dữ liệu cũ ..


0

Nếu bạn muốn cập nhật danh sách giao diện người dùng từ một dịch vụ, thì hãy đặt bộ điều hợp tĩnh trong hoạt động Chính của bạn và thực hiện việc này:

@Override
public void onDestroy() {
    if (MainActivity.isInFront == true) {
        if (MainActivity.adapter != null) {
            MainActivity.adapter.notifyDataSetChanged();
        }

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    

0

Nếu bạn đang đi bởi các đường dẫn android và bạn đang sử dụng ContentProvidersđể lấy dữ liệu từ Databasevà bạn đang hiển thị nó trong ListViewsử dụng CursorLoaderCursorAdapters, sau đó bạn tất cả các thay đổi đối với dữ liệu có liên quan sẽ tự động được phản ánh trong ListView.

Của bạn getContext().getContentResolver().notifyChange(uri, null);trên con trỏ vào ContentProvidersẽ đủ để phản ánh những thay đổi .no nhu cầu cho công việc thêm xung quanh.

Nhưng khi bạn không sử dụng tất cả những thứ này thì bạn cần nói với bộ điều hợp khi tập dữ liệu đang thay đổi. Ngoài ra, bạn cần phải điền lại / tải lại tập dữ liệu của bạn (nói danh sách) và sau đó bạn cần gọi notifyDataSetChanged()trên bộ chuyển đổi.

notifyDataSetChanged()Sẽ không hoạt động nếu không có thay đổi trong datset. Dưới đây là nhận xét trên phương thức trong tài liệu-

/**
 * Notifies the attached observers that the underlying data has been changed
 * and any View reflecting the data set should refresh itself.
 */

0

Tôi chỉ có thể nhận thông báoDataSetChanged bằng cách lấy dữ liệu bộ điều hợp mới, sau đó đặt lại bộ điều hợp cho chế độ xem danh sách, sau đó thực hiện cuộc gọi như vậy:

    expandableAdapter = baseFragmentParent.setupEXLVAdapter();
    baseFragmentParent.setAdapter(expandableAdapter);
    expandableAdapter.notifyDataSetChanged(); 

0

trên tùy chọn khác là onWindowFocusChangedphương thức, nhưng chắc chắn nó nhạy và cần một số mã hóa bổ sung cho ai quan tâm

 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
    }

0

Hãy xem xét bạn đã thông qua một danh sách cho bộ chuyển đổi của bạn.
Sử dụng:

list.getAdapter().notifyDataSetChanged()

để cập nhật danh sách của bạn.


0

Nếu tôi nói về kịch bản của mình ở đây, các câu trả lời ở trên sẽ không hoạt động vì tôi có hoạt động hiển thị danh sách các giá trị db cùng với nút xóa và khi nhấn nút xóa, tôi muốn xóa mục đó khỏi danh sách.

Điều thú vị là, tôi không sử dụng chế độ xem tái chế mà là chế độ xem danh sách đơn giản và chế độ xem danh sách đó được khởi tạo trong lớp bộ điều hợp. Vì vậy, việc gọi notifyDataSetChanged()sẽ không làm bất cứ điều gì bên trong lớp bộ điều hợp và ngay cả trong lớp hoạt động nơi đối tượng bộ điều hợp được khởi tạo vì phương thức xóa nằm trong lớp bộ điều hợp.

Vì vậy, giải pháp là xóa đối tượng khỏi bộ điều hợp trong getViewphương thức lớp bộ điều hợp (chỉ xóa đối tượng cụ thể đó nhưng nếu bạn muốn xóa tất cả, hãy gọi clear()).

Để bạn có một số ý tưởng, mã của tôi trông như thế nào,

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
         }
    });
 //....

Lưu ý: ở đây remove()getItem()các phương thức được kế thừa từ lớp Adaptor.

  • remove() - để xóa mục cụ thể được nhấp
  • getItem(position) - là để lấy mục (ở đây, đó là đối tượng Word của tôi mà tôi đã thêm vào danh sách) từ vị trí được nhấp.

Đây là cách tôi đặt bộ điều hợp cho listview trong lớp hoạt động,

    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);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.