【问题标题】:Android infinite Scroll List viewAndroid无限滚动列表视图
【发布时间】:2014-12-12 20:01:57
【问题描述】:

我想实现OnScrollListener 以在滚动到底部时动态加载更多数据。以下代码给了我 NullPointerException,但是当我声明

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

setBusiness 内部,它没有显示任何错误并且工作正常。问题是当我滚动到页面底部时,它会用新数据替换 list view 中的当前数据,但我想要的是在附加新数据而不是替换时无限滚动,以便我可以查看第一个向上滚动的数据

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

}

这里是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)

【问题讨论】:

  • 我已经附上了logcat
  • java.lang.NullPointerException at com.sp.sodhpuch.adapters.BusinessListDataAdapter.getCount(BusinessListDataAdapter.java:53) - 检查 BusinessListDataAdapter.java,第 53 行

标签: android infinite-scroll custom-adapter onscrolllistener


【解决方案1】:

你需要做三件事。

1) 创建将向适配器列表添加十个项目的方法。

2) 在列表视图页脚中添加包含按钮的 xml。

3) 然后在调用步骤 1 方法的活动或片段类中为该按钮编写 clickListener,然后只需重置列表视图适配器。

【讨论】:

    【解决方案2】:

    来自Android - ListView to load more items when reached end

    您可以在 listView 上添加一个页脚,该页脚将有一个名为 LoadMore 的按钮。这是一个完整的教程List With Load more 或者您可以实现 onscrolllistener() 并将此侦听器添加到您的 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();
        }
    }
    }
    

    【讨论】:

    • 我的问题是没有实现加载更多或 OnScrollListener。 OnScrollListener 正在工作,但新获取的数据替换了列表中的先前数据,我想要的是追加新数据以追加到当前数据下方
    【解决方案3】:

    嗨@carefree,这是一个解决方案,它可能会为您提供您想要实现的目标 https://github.com/rahulinaction/ImageGrid

    【解决方案4】:

    问题最有可能出在您的任务和适配器上,而不是列表滚动。 您可以在您的 listAdapter 中实现一个方法 addItems,如下所示:

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

    在您的任务的 onPostExecute 或您使用的任何回调中,检查 listAdapter 是否有项目,然后调用 addItems 将新获取的项目传递给它。否则,启动并填充获取的数据集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      • 2013-08-24
      • 1970-01-01
      相关资源
      最近更新 更多