Search code examples
androidlistviewscrollnotifydatasetchanged

Android ListView append more items notifyDataSetChanged() not working


I'm trying to append more items to a listview in an Android project. This is my the code I am using:

public class NewsFeedActivity extends ListActivity implements FetchDataListener{

boolean loadingMore = false;

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

    SharedPreferences shared = getSharedPreferences(MainActivity.class.getSimpleName(),Context.MODE_PRIVATE);
    @SuppressWarnings("unused")
    String storedUID = (shared.getString(UID, ""));

    final ListView list = (ListView)findViewById(android.R.id.list);
    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeLayout.setColorSchemeResources(R.color.black, R.color.white, R.color.black, R.color.white);
    swipeLayout.setOnRefreshListener(new OnRefreshListener() {

        @Override
        public void onRefresh() {
             new Handler().postDelayed(new Runnable() {
                    @Override public void run() {
                        swipeLayout.setRefreshing(false);
                        loadingMore = true;
                        initView();
                    }
                }, 1000);

        }

    });

    list.setOnScrollListener(new OnScrollListener(){

        private int currentFirstVisibleItem;
        private int currentVisibleItemCount;
        private int totalItem;

        @Override
           public void onScrollStateChanged(AbsListView view, int scrollState) {
               this.isScrollCompleted();  
           }

           private void isScrollCompleted() {
            // TODO Auto-generated method stub
               int lastInScreen = currentFirstVisibleItem + currentVisibleItemCount;    
               if((lastInScreen == totalItem) && !(loadingMore)){     
                   //Toast.makeText(getApplicationContext(), "Loading more...", Toast.LENGTH_LONG).show();
                   loadingMore = true;
                   initView();


               }
           }



        @Override
           public void onScroll(AbsListView view, int firstVisibleItem,
           int visibleItemCount, int totalItemCount) {

            this.currentFirstVisibleItem = firstVisibleItem;
            this.currentVisibleItemCount = visibleItemCount;
            this.totalItem = totalItemCount;
        }

          });


    initView();

}

and here are the other two functions I'm using to call the list in:

private void initView() {
    // show progress dialog
    if(!loadingMore == true){
    dialog = ProgressDialog.show(this, "", "Loading...");
    }
    String url = SERVER_URL+getBlackCards;
    FetchDataTask task = new FetchDataTask(this);
    task.execute(url);
}

public void onFetchComplete(List<Application> data) {
    // dismiss the progress dialog

    if(dialog != null)  dialog.dismiss();
    // create new adapter
    ApplicationAdapter adapter = new ApplicationAdapter(this, data);
    // set the adapter to list

    setListAdapter(adapter);  

    if(loadingMore == true){
        adapter.notifyDataSetChanged();
    }

    loadingMore = false;
}

The current behaviour is essentially just a refresh where all items are replaced and I am scrolled back up to the top of the list. After doing some looking around I found a lot of example that used notifyDataSetChanged() to append items but it seems to have no effect for me.


Solution

  • The current behavior is essentially just a refresh where all items are replaced and I am scrolled back up to the top of the list

    Because here:

     ApplicationAdapter adapter = new ApplicationAdapter(this, data);
     setListAdapter(adapter);  
    

    Every time creating new object of adapter class instead of adding new items in current adapter of ListView.

    Do it as:

    1. Create ApplicationAdapter object at class level as:

    ApplicationAdapter adapter;
    public void onFetchComplete(List<Application> data) {
        // dismiss the progress dialog
    
        if(dialog != null)  dialog.dismiss();
        // create new adapter
        if(adapter==null){
        adapter = new ApplicationAdapter(this, data);
        // set the adapter to list
        setListAdapter(adapter);  
        }else{
             // update current adapter
        }
        loadingMore = false;
    }
    

    2. Create a addAllItems method in ApplicationAdapter class:

    public void addAllItems(List<Application> data){
      this.data.addAll(data);
      this.notifyDataSetChanged();
    }
    

    3. Now call addAllItems in else part of onFetchComplete method:

      adapter.addAllItems(data);