Search code examples
androidandroid-listviewandroid-asynctaskbaseadapteronscrolllistener

Refresh ListView with custom adapter that extends BaseAdapter


I'm using ListView which is populated by custom adapter that extends BaseAdapter. Data is fetched from external server with AsyncTask and onPostExecute method of AsyncTask calls a method on ListActivity that sets adapter to display data

ListView also implements OnScrollListener to fetch data on scroll and add to bottom.

I've an ActionBar (Toolbar) with custom view which contains EditText fields and Button on click of which, again, same AsyncTask is called to fetch new data with query values passed from Toolbar.

Problem is, when button on toolbar is clicked I want the ListView to be populated with entirely new data replacing the old values but instead new data is appended at the bottom of list ( as if OnClickListener is called).

I checked Link1, Link2 but none seem to help

And of course main strike would be to use NotifyDataSetChange and I'm using that too but not worth it.

My method to set adapter

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

}

setting custom toolbar with search fields

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

}

Methods to fetch data from server

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

Solution

  • You are using .addAll() which appends data to the data the adapter already has. The quick-fix is to just drop all data prior to calling .addAll() by using .clear().

    //...
    this.businesses.clear();
    this.businesses.addAll(businesses);
    adapter.notifyDataSetChanged();
    //...