使用扩展 BaseAdapter 的自定义适配器刷新 ListView

Refresh ListView with custom adapter that extends BaseAdapter

我正在使用 ListView,它由扩展 BaseAdapter 的自定义适配器填充。使用 AsyncTask 从外部服务器获取数据,AsyncTask 的 onPostExecute 方法调用 ListActivity 上的方法,设置适配器以显示数据

ListView 还实现了 OnScrollListener 以获取滚动数据并添加到底部。

我有一个带有自定义视图的 ActionBar (Toolbar),其中包含 EditText 字段和 Button 单击其中,同样 AsyncTask 被调用以使用从 Toolbar 传递的查询值获取新数据。

问题是,当单击工具栏上的按钮时,我希望 ListView 填充全新数据以替换旧值,而是将新数据附加到列表底部(就像 OnClickListener 被调用)。

我检查了 Link1, Link2 但 none 似乎有帮助

当然,主要的打击是使用 NotifyDataSetChange,我也在使用它,但不值得。

我设置适配器的方法

public void setBusinesses(ArrayList<BusinessListData> businesses) {

    imgFetcher = new BusinessListIconTask(this);
    layoutInflator = LayoutInflater.from(this);
    if (this.businesses == null || adapter == null) {
        this.businesses = new ArrayList<>();
        adapter = new BusinessListDataAdapter(this, imgFetcher,
                layoutInflator, this.businesses);
        businessList.setAdapter(adapter);
    }
    this.businesses.addAll(businesses);
    adapter.notifyDataSetChanged();

    /* Activates when scrolling to bottom of list */
    businessList.setOnScrollListener(new OnScrollListener() {
        public int currentScrollState;
        public int currentFirstVisibleItem;
        public int currentVisibleItemCount;
        public int totalItemCount;
        public int lastItem;
        boolean isLoading = false;

        public void onScrollStateChanged(AbsListView view, int scrollState) {
            this.currentScrollState = scrollState;
            this.isScrollCompleted();

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                             int visibleItemCount, int totalItemCount) {
            this.currentFirstVisibleItem = firstVisibleItem;
            this.currentVisibleItemCount = visibleItemCount;
            this.totalItemCount = totalItemCount;
            this.lastItem = firstVisibleItem + visibleItemCount;
        }

        private void isScrollCompleted() {
            if (this.lastItem == this.totalItemCount) {
                /*** In this way I detect if there's been a scroll which has completed ***/
                if (!isLoading) {
                    isLoading = true;
                    getScrollData(metroTxt, metroLoc, metroId);
                }
            } else {
                businessList.removeFooterView(footerView);
            }
        }
    });

}

设置带有搜索字段的自定义工具栏

void showCustomView(String metroTxt, String metroLoc, String metroId) {
    LayoutInflater mInflater = LayoutInflater.from(this);

    if (mCustomView == null)
        mCustomView = mInflater.inflate(R.layout.custom_action_bar, null);
    mToolbar.removeView(mCustomView);
    mToolbar.addView(mCustomView);
    Log.d("I'm inside custom view", "txt" + metroTxt);
    abKeyword = (CustomAutoCompleteTextView) mCustomView
            .findViewById(R.id.ab_keyword);
    abLocation = (CustomAutoCompleteTextView) mCustomView
            .findViewById(R.id.ab_location);
    ab_search = (Button) mCustomView
            .findViewById(R.id.ab_search);
    abKeyword.append(metroTxt);

    abLocation.setVisibility(View.GONE);
    ab_search.setVisibility(View.GONE);

    abKeyword.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {

            if (hasFocus || !abKeyword.getText().toString().isEmpty() || !abLocation.getText().toString().isEmpty()) {
                abLocation.setVisibility(View.VISIBLE);
                ab_search.setVisibility(View.VISIBLE);
            } else {
                abLocation.setVisibility(View.GONE);
                ab_search.setVisibility(View.GONE);
            }
        }
    });
    abKeyword.addTextChangedListener(new TextWatcher() {

        public void afterTextChanged(Editable editable) {
            // TODO Auto-generated method stub

        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {
            // TODO Auto-generated method stub
        }

        public void onTextChanged(CharSequence s, int start, int before,
                                  int count) {

            String newText = s.toString();

            BusinessInfoSuggestionTask autocompleteTask = new BusinessInfoSuggestionTask(BusinessResultListActivity.this);
            String acType = "keyword";

            if (s.length() >= 1) {
                abLocation.setVisibility(View.VISIBLE);
                ab_search.setVisibility(View.VISIBLE);
                autocompleteTask.execute(newText, acType, cActivity);

            } else {
                abLocation.setVisibility(View.GONE);
                ab_search.setVisibility(View.GONE);
            }

        }

    });
    ab_search.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            String abKey = abKeyword.getText().toString();
            String abLoc = abLocation.getText().toString();
            String abId = "";
            getBusinesses(abKey, abLoc, abId);
            Log.d("I'm clicked", "button on toolbar clicked");
        }
    });

}

从服务器获取数据的方法

/* Get Businesses data from server */
private void getBusinesses(String metroTxt, String metroLoc, String metroId) {
    // TODO Auto-generated method stub
    String first = "first";
    BusinessListApiTask spTask = new BusinessListApiTask(
            BusinessResultListActivity.this);
    try {
        spTask.execute(metroTxt, metroLoc, metroId, first);
    } catch (Exception e) {
        spTask.cancel(true);
    }
}

/* Fetch more data on scroll */
private void getScrollData(String metroTxt, String metroLoc, String metroId) {
    // TODO Auto-generated method stub
    String first = "next";
    BusinessListApiTask spTask = new BusinessListApiTask(
            BusinessResultListActivity.this);
    try {
        spTask.execute(metroTxt, metroLoc, metroId, first); //Call AsyncTask to fetch data from server
    } catch (Exception e) {
        spTask.cancel(true);
    }
}

您正在使用 .addAll() 将数据附加到适配器已有的数据。快速修复是在使用 .clear().

调用 .addAll() 之前删除所有数据
//...
this.businesses.clear();
this.businesses.addAll(businesses);
adapter.notifyDataSetChanged();
//...