簡體   English   中英

帶自定義BaseAdapter的notifyDataSetChanged在ListView中不起作用

[英]notifyDataSetChanged does not work in the ListView with custom BaseAdapter

我嘗試創建ListView。 它包含由單個xml模板創建的少量自定義視圖,以及一個用於指示進度的視圖。 ProgressView始終必須位於自定義ListView的底部。 所以,這是代碼:

public class SearchActivity extends Activity implements OnXMLDataGetterComplete {

    private ListView mMainLayout;
    private HotelsListAdapter mHotelsListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        mHotelsListAdapter = new HotelsListAdapter(); //create my custom adapter
        mHotelsListAdapter.setLoading(true); //sets that my ListView will be show ProgressView at the bottom

        mMainLayout = (ListView) findViewById(R.id.search_activity_layout);
        mMainLayout.setAdapter(mHotelsListAdapter); //set adapter for my ListView

        getData(); //start to receive data from web
    }

    //this function runs after HTTP-query
    public void onGetData(final List data) { //receives list of some data
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Iterator<XMLDataGetter.HotelListXMLParser.HotelListXMLEntry> it = data.iterator();
                while (it.hasNext()) {
                    XMLDataGetter.HotelListXMLParser.HotelListXMLEntry item = it.next();
                    mHotelsListAdapter.setLoading(data.size() != 0);
                    HotelItemView hotel = new HotelItemView(SearchActivity.this); //create some custom view by received data
                    ...
                    mHotelsListAdapter.addItem(hotel); //add this view to the adapter
                }
                mHotelsListAdapter.notifyDataSetChanged(); //THIS NOT WORKS
            }
        }
    }

    public class HotelsListAdapter extends BaseAdapter { //ny custom adapter

        private List<HotelItemView> mItems = new ArrayList<HotelItemView>(); //list, which contains all created custom views
        private boolean mIsLoading = false; //variable, which determines, whether ProgressView will be shown
        private RelativeLayout mLoadingView; //layout of activity

        public HotelsListAdapter() {
            LayoutInflater inflater = (LayoutInflater) ((Context) SearchActivity.this).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mLoadingView = (RelativeLayout) inflater.inflate(R.layout.hotel_list_loading, null); //inflate ProgressView
        }

        @Override
        public boolean areAllItemsEnabled() {
            return true;
        }

        @Override
        public boolean isEnabled(int position) {
            return true;
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public int getCount() {
            if (mIsLoading)
                return mItems.size() + 1; //custom adapter contains children vies + ProgressView
            else
                return mItems.size(); //custom adapter contains only children views
        }

        @Override
        public Object getItem(int position) {
            if (position > mItems.size() - 1)
                return mLoadingView; //return ProgressView
            else
                return mItems.get(position); //return child view
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return (View) getItem(position);
        }

        @Override
        public int getItemViewType(int position) {
            return 0;
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        public void addItem(HotelItemView item) {
            mItems.add(item);
        }

        public void clear() {
            mItems.clear();
        }

        public void setLoading(boolean loading) {
            mIsLoading = loading;
        }

        public boolean isLoading() {
            return mIsLoading;
        }
    }
}

此示例帶有ProgressBarView,但我嘗試刪除有關它的引用:

    @Override
    public int getCount() {
        return mItems.size(); //custom adapter contains only children views
    }

    @Override
    public Object getItem(int position) {
        return mItems.get(position); //return child view
    }

並且notifyDataSetChanged()仍然無法正常工作。 我怎么了 我無法顯示添加的視圖。

我試圖在otifyDataSetChanged()之前添加mMainLayout.invalidateViews()。 因此,我看到了我的視圖列表,但是每三到五次出現異常“適配器的內容已更改,但ListView並未收到通知”。 我該怎么辦?

最主要的是,我不需要清除適配器。 添加子視圖必須是增量的。 我也嘗試擴展ListAdapter,但是它根本沒有這樣的方法

也許不要覆蓋適配器的registerDataSetObserver方法。

其他一些提示:

如果沒有理由不使用它,我建議您使用ArrayAdapter,因為它可以為您節省一些基本配置並為您處理列表管理。 另外,不要將“視圖”保存在要顯示的列表中,而是保存包含數據的項目。 ListAdapters可以為您回收視圖,因此列表中的每個項目都沒有一個視圖,但是可見的每個項目都沒有一個視圖。 在getView方法中,如果“ convertView”參數不為空,則可以重用此視圖,因此只需填充其數據並返回即可。 這將提高列表的性能,並大大減少內存消耗。

對於Async東西,最好使用AsyncTask,它與Android系統更好地集成在一起,並且在后台任務之前和之后在UI Thread中運行東西等事情變得更加容易。

嘗試

mHotelsListAdapter.setNotifyOnChange(true);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM