简体   繁体   中英

Android infinite Scroll List view

I want to implement OnScrollListener to load more data, when scrolled to bottom, dynamically. Following code is giving me NullPointerException, but when I declare

 BusinessListDataAdapter adapter = new BusinessListDataAdapter(this, this.imgFetcher, this.layoutInflator, this.businesses);

inside setBusiness , it doesn't show any error and works fine. Problem with this is when I scroll to the bottom of page it replaces current data in list view with new data but what I wanted is endless scrolling while appending new data instead of replacing so that I can view first data scrolling up

import java.util.ArrayList;

import com.sp.sodhpuch.adapters.BusinessListDataAdapter;
import com.sp.sodhpuch.data.BusinessListData;
import com.sp.sodhpuch.tasks.BusinessListApiTask;
import com.sp.sodhpuch.tasks.BusinessListIconTask;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ListResultActivity extends Activity {

    private ArrayList<BusinessListData> businesses;
    private ListView businessList;
    private LayoutInflater layoutInflator;
    private BusinessListIconTask imgFetcher;
    BusinessListDataAdapter adapter = new BusinessListDataAdapter(this,
            this.imgFetcher, this.layoutInflator, this.businesses);

    @SuppressWarnings("unchecked")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.businesslist);
        getData();
//      @SuppressWarnings("deprecation")
//      final Object[] data = (Object[]) getLastNonConfigurationInstance();
//      if (data != null) {
//          setContentView(R.layout.businesslist);
//          this.businessList = (ListView) findViewById(R.id.lvBusinesslist);
//          this.imgFetcher = new BusinessListIconTask(this);
//          this.layoutInflator = LayoutInflater.from(this);
//
//          this.businesses = (ArrayList<BusinessListData>) data[0];
//          this.imgFetcher = (BusinessListIconTask) data[1];
//          businessList.setAdapter(adapter);
//      }
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        Object[] myStuff = new Object[2];
        myStuff[0] = this.businesses;
        myStuff[1] = this.imgFetcher;
        return myStuff;
    }

    /**
     * Bundle to hold refs to row items views.
     * 
     */
    public static class MyViewHolder {
        public TextView businessName, businessAddress, phoneNo;
        public Button btnProfile;
        public ImageView icon;
        public BusinessListData business;
    }

    public void setBusinesses(ArrayList<BusinessListData> businesses) {
        this.businessList = (ListView) findViewById(R.id.lvBusinesslist);

        this.imgFetcher = new BusinessListIconTask(this);
        this.layoutInflator = LayoutInflater.from(this);
        this.businesses = businesses;
        this.businessList.setAdapter(adapter);
        businessList.setOnScrollListener(new OnScrollListener() {
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                if (businessList.getLastVisiblePosition() == totalItemCount - 1) {
                    getData();
//                  adapter.notifyDataSetChanged();
                }

            }
        });

    }

    private void getData() {
        // TODO Auto-generated method stub
        Intent myIntent = getIntent();

        // gets the arguments from previously created intent
        String metroTxt = myIntent.getStringExtra("key");
        String metroLoc = myIntent.getStringExtra("loc");
        String metroId = myIntent.getStringExtra("qt");

        BusinessListApiTask spTask = new BusinessListApiTask(
                ListResultActivity.this);

        try {
            spTask.execute(metroTxt, metroLoc, metroId);

        } catch (Exception e) {
            spTask.cancel(true);
        }
    }

}

Here is logcat

10-17 04:50:51.897: W/dalvikvm(6942): threadid=1: thread exiting with uncaught exception (group=0xb1d41b20)
10-17 04:50:51.897: E/AndroidRuntime(6942): FATAL EXCEPTION: main
10-17 04:50:51.897: E/AndroidRuntime(6942): Process: com.sp.sodhpuch, PID: 6942
10-17 04:50:51.897: E/AndroidRuntime(6942): java.lang.NullPointerException
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.sp.sodhpuch.adapters.BusinessListDataAdapter.getCount(BusinessListDataAdapter.java:53)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.widget.ListView.setAdapter(ListView.java:480)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.sp.sodhpuch.ListResultActivity.setBusinesses(ListResultActivity.java:78)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.sp.sodhpuch.tasks.BusinessListApiTask.onPostExecute(BusinessListApiTask.java:119)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.sp.sodhpuch.tasks.BusinessListApiTask.onPostExecute(BusinessListApiTask.java:1)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.os.AsyncTask.finish(AsyncTask.java:632)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.os.Handler.dispatchMessage(Handler.java:102)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.os.Looper.loop(Looper.java:136)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at android.app.ActivityThread.main(ActivityThread.java:5017)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at java.lang.reflect.Method.invokeNative(Native Method)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at java.lang.reflect.Method.invoke(Method.java:515)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
10-17 04:50:51.897: E/AndroidRuntime(6942):     at dalvik.system.NativeStart.main(Native Method)

You need to do three things.

1) Create Method which will add ten more items to adapter list.

2) Add xml that contain button in listview footer.

3) Then write clickListener for that button in activity or fragment class in which you call step 1 method and then just reset the listview adapter.

From Android - ListView to load more items when reached end

You can add a footer on the listView which will have a button named LoadMore. Here is a complete tutorial List With Load more Or you can implement onscrolllistener() and add this listener to your ListView

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

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

private void isScrollCompleted() {
    if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) {
        /*** In this way I detect if there's been a scroll which has completed ***/
        /*** do the work for load more date! ***/
        if(!isLoading){
         isLoading = true;
         loadMoreData();
    }
}
}

嗨@carefree 这里是一个解决方案,它可能会让你得到你想要实现的目标https://github.com/rahulinaction/ImageGrid

The problem most likely to be with your task and adapter not with list scrolling. You can implement a method, addItems, in your listAdapter as follows:

    public void addItems(BusniessListData... newItems){
        for(BusniessListData newItem : newItems){
            this.businesses.add(newItem);
        }           
        notifyDataSetChanged();
    }

In onPostExecute of your task, or whatever callback you use, check if listAdapter has items, then call addItems passing it newly fetched items. Otherwise, initiate and populate fetched data-set.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM