thông báo ví dụDataSetChanged


166

Tôi đang cố gắng để sử dụng trong tôi Android Applicationnhững notifyDataSetChanged()phương pháp cho một ArrayAdapternhưng nó không làm việc cho tôi.

Tôi tìm thấy như câu trả lời ở đây , notifyDataSetChanged()nên chạy trong luồng chính, nhưng không có ví dụ nào cho điều đó.

Bất cứ ai cũng có thể gửi một ví dụ hoặc ít nhất là một liên kết?!



bạn có thể kiểm tra blog này và ví dụ này trong githubđiều này nữa
Cabezas

Câu trả lời:


328

Đối với một ArrayAdapter, notifyDataSetChangedchỉ có tác dụng nếu bạn sử dụng add(), insert(), remove(), và clear()trên Adapter.

Khi một ArrayAdapterđược xây dựng, nó giữ tham chiếu cho Listcái đã được truyền vào. Nếu bạn chuyển qua Listmột thành viên của một Hoạt động và thay đổi thành viên Hoạt động đó sau đó, ArrayAdapterthì vẫn giữ một tham chiếu đến bản gốc List. Bộ điều hợp không biết bạn đã thay đổi Listtrong Hoạt động.

Lựa chọn của bạn là:

  1. Sử dụng các chức năng của ArrayAdapterđiều chỉnh Danh mục cơ bản ( add(), insert(), remove(), clear(), vv)
  2. Tạo lại ArrayAdaptervới Listdữ liệu mới . (Sử dụng nhiều tài nguyên và thu gom rác.)
  3. Tạo lớp của riêng bạn xuất phát từ BaseAdapterListAdaptercho phép thay đổi Listcấu trúc dữ liệu cơ bản .
  4. Sử dụng notifyDataSetChanged()mỗi khi danh sách được cập nhật. Để gọi nó trên giao diện người dùng-Thread, sử dụng runOnUiThread()của Activity. Sau đó, notifyDataSetChanged()sẽ làm việc.

13
cũng cẩn thận khi gán các đối tượng 'mới' cho dữ liệu của bạn. thay vào đó, hãy sử dụng xóa (), lặp lại / thực hiện thay đổi dữ liệu, sau đó gọi notifyDataInChanged ()
moonlightcheese

Nhưng nếu chúng ta gọi notifyDataSetChanged()theo cách như vậy : ((BaseAdapter) arrayAdapter).notifyDataSetChanged();?
teoREtik

2
Tôi sử dụng BaseExpandableListAd CHƯƠNG, nó không có các hàm add () hoặc remove () vì vậy tôi lưu trữ Bản đồ của mình dưới dạng biến thành viên. Tôi cập nhật Bản đồ và gọi notifyDatasetChanged () nhưng không có gì xảy ra. Khi tôi sử dụng lựa chọn số 4, nó hoạt động. Tại sao???
emeraldhieu

Tôi đang sử dụng ArrayAd CHƯƠNG cho GridView tùy chỉnh, tôi đang thêm hình ảnh khi tôi nhận được chúng từ các url bằng cách gọi adapter.add (dataReceured). Điều này hoạt động tốt thêm dữ liệu nhưng tại sao nó làm mới và lên đầu. Tôi muốn hiển thị các mục vì chúng sẽ được thêm mà không cần làm mới danh sách. (Điều muốn làm là làm việc với GridView của Android bằng cách sử dụng notifyDatasetChanged ()) Làm cách nào tôi có thể làm cho nó hoạt động trong customGridView này (StaggeredGridView).
Nhà truyền giáo di động

1
Tôi đã thử tạo BaseAd CHƯƠNG của riêng mình để thêm các phương thức sắp xếp vào danh sách, nhưng vì một số lý do, nó chỉ không hoạt động. Không phải là ứng dụng của tôi chậm ngay cả khi tôi tạo lại toàn bộ bộ điều hợp với một danh sách mảng được sắp xếp, nhưng nó vẫn làm tôi khó chịu. Làm thế nào chính xác nó sẽ tạo ra rất nhiều rác mặc dù? Tôi giả sử mảng thực tế của dữ liệu tốn kém được giữ làm tham chiếu trong hoạt động gọi bộ điều hợp, nghĩa là chỉ bộ điều hợp sẽ được thu thập.
G_V

34

Bạn có thể sử dụng runOnUiThread()phương pháp như sau. Nếu bạn không sử dụng a ListActivity, chỉ cần điều chỉnh mã để có được tham chiếu đến ArrayAdapter.

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

1
Tôi đã cố gắng thêm đoạn mã của bạn vào mã của mình (bạn có thể tìm thấy nó ở đây stackoverflow.com/questions/3667442/how-to-refresh-ad CHƯƠNG ) trong phương thức onCreate, nhưng tôi vẫn không thành công :( Có lẽ đó là sai chỗ khi thêm nó?!
Tima

1
Câu hỏi của bạn chỉ hỏi làm thế nào bạn có thể gọi phương thức và để nó chạy trong luồng UI chính. Câu trả lời này. Trong trường hợp cụ thể của bạn ( stackoverflow.com/questions/3670500/ trên ) AsyncTask và phương thức onPostExecute () của nó dường như là những gì bạn nên xem xét.
Brian

12

Gần đây tôi đã viết về chủ đề này, mặc dù bài đăng này đã cũ, tôi nghĩ nó sẽ hữu ích cho ai đó muốn biết cách thực hiện BaseAdapter.notifyDataSetChanged() từng bước và một cách chính xác.

Vui lòng làm theo Cách triển khai chính xác BaseAd CHƯƠNG.notifyDataSetChanged () trong Android hoặc blog mới hơn BaseAd Module.notifyDataSetChanged () .


Xin chào, tôi đã thử ví dụ liên kết đầu tiên, nhưng thay vì mItem.add(), tôi đã chỉ chỉnh sửa một yếu tố có nghĩa là mItem.get(position).setImage(encodedImage)có thể đó là lý do tại sao nó gây ra lỗi NullPulum. Vì vậy, thông báoDataSetChange chỉ hoạt động khi chỉnh sửa nó, bcz cho bộ điều hợp Array được đề cập ở trên nó hoạt động chỉ dành cho add (), clear (), remove (), v.v.
Shuxant N

notifyDataSetChanged sẽ hoạt động để chỉnh sửa hoặc sửa đổi tập dữ liệu, con trỏ null của bạn là do một cái gì đó khác, kiểm tra nhật ký.
Arif Nadeem

7

Tôi đã có cùng một vấn đề và tôi không muốn thay thế toàn bộ ArrayAd CHƯƠNG bằng một phiên bản mới liên tục. Vì vậy, tôi có Adaptor làm việc nặng nhọc ở một nơi khác.

Thêm phần này vào nơi bạn thường (cố gắng) gọi thông báo

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

Lớp AdHelper

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

Tôi có một vài ArrayAd chương khác trong mã của mình và chúng đã hoạt động mà không gặp vấn đề gì. Tối nay, tôi quyết định biến một SimpleCthonAd CHƯƠNG thành một ArrayAd CHƯƠNG, và nó KHÔNG LÀM VIỆC. Sau khi vật lộn với nó trong vài giờ và cố gắng tìm ra lý do tại sao nó không hoạt động, tôi đã tìm thấy lớp Adaptor của bạn và NGAY BÂY GIỜ LÀM VIỆC! Cảm ơn!
kiêu hãnh

1
Điều này có thể dễ dàng được thực hiện trong một hàm ... TẠI SAO bạn sẽ khởi tạo một lớp mới cho nó?
techiService

2
Trong các hàm Java được gọi là các phương thức. Bạn có đề xuất gì, có phương pháp có thể tái sử dụng cao này trong cùng lớp với Bộ điều hợp mảng không? Hoặc Fragment / Activity chứa danh sách xem? Vì vậy, có, nó trong một lớp học, nơi nó có thể được tái sử dụng. Nếu bạn muốn làm cho nó tĩnh bằng mọi cách hãy tiếp tục.
Kevin Parker

1
Ý kiến ​​hay. Một cách khác là mở rộng ArrayAd CHƯƠNG, được đặt tên là ArrayAd ModuleCompat và ghi đè phương thức addAll (..), vì phương thức này chỉ khả dụng kể từ API 11. Trong đó, hãy kiểm tra mức API và sử dụng super.addAll(..)cho API> 11 và super.add (.. ) kết hợp với phép lặp như của bạn : if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Bây giờ chỉ cần mở rộng từ lớp bộ điều hợp mới của bạn.
Konsumierer

Hoàn hảo! Cảm ơn rất nhiều @Kevin - đây chính xác là những gì tôi cần!
Kibi

3

Tôi biết đây là phản hồi muộn nhưng tôi đã gặp phải một vấn đề tương tự và tôi đã giải quyết nó bằng cách sử dụng notifyDataSetChanged() đúng nơi.

Vì vậy, tình hình của tôi là như sau.

Tôi đã phải cập nhật một listview trong tab thanh hành động (đoạn) với nội dung được trả về từ một hoạt động hoàn toàn khác. Tuy nhiên, ban đầu, listview sẽ không phản ánh bất kỳ thay đổi nào. Tuy nhiên, khi tôi nhấp vào một tab khác và sau đó quay lại tab mong muốn, listview sẽ được cập nhật với nội dung chính xác từ hoạt động khác. Vì vậy, để giải quyết điều này tôi đã sử dụngnotifyDataSetChanged() bộ điều hợp thanh hành động trong mã của hoạt động phải trả lại dữ liệu.

Đây là đoạn mã mà tôi đã sử dụng trong hoạt động.

@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).
    }
}

Hoạt động này sẽ trả về một số dữ liệu FragmentTab2và nó sẽ trực tiếp cập nhật danh sách của tôi vào FragmentTab2.

Hy vọng ai đó thấy điều này hữu ích!

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.