android - 无法通过无限滚动加载数据

标签 android json android-fragments endlessscroll

我是 Android 的新手,有一段时间卡住了。 我在一家公司实习,但没有人可以提供建议。我的应用程序类似于 RSS 提要。我必须从返回 JSON 对象的 API 加载数据。 API地址为http://itvdn-api.azurewebsites.net/api/news/1 .目前只有4页。我立即从第一页加载信息,然后当还剩 2 个项目时,我尝试加载下一个。它加载第二页但随后停止加载。我尝试调试,在它解析第 3 页后,我被扔到 AbsListView.java。应用程序运行良好,没有任何崩溃。

这是 Fragment 类,我在其中表示已解析的数据。

public class NewsFragment extends android.support.v4.app.Fragment implements AbsListView.OnItemClickListener {

private static final String ARG_SECTION_NUMBER = "section_number";

private ArrayList<NewsBlogData> newsData;


private OnFragmentInteractionListener mListener;

/**
 * The fragment's ListView/GridView.
 */
private AbsListView mListView;

/**
 * The Adapter which will be used to populate the ListView/GridView with
 * Views.
 */
private NewsBlogItemAdapter mAdapter;

// TODO: Rename and change types of parameters
public static NewsFragment newInstance(int sectionNumber) {
    NewsFragment fragment = new NewsFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

/**
 * Mandatory empty constructor for the fragment manager to instantiate the
 * fragment (e.g. upon screen orientation changes).
 */
public NewsFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    // TODO: Change Adapter to display your content
    /*mAdapter = new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
            android.R.layout.simple_list_item_1, android.R.id.text1, DummyContent.News);*/
    newsData = new ParserJson().getNewsBlogData(1);
    mAdapter = new NewsBlogItemAdapter(getActivity(),
            R.layout.news_blog_list_item,
            newsData);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_news, container, false);

    // Set the adapter
    mListView = (AbsListView) view.findViewById(android.R.id.list);
    mListView.setAdapter(mAdapter);

    // Set OnItemClickListener so we can be notified on item clicks
    mListView.setOnItemClickListener(this);
    //mListView.setOnScrollListener(new EndlessScrollListener());
    mListView.setOnScrollListener(new EndlessScrollListener() {

        @Override
        public void onLoadMore(int page, int totalItemsCount) {
            // TODO Auto-generated method stub
            newsData.addAll(new ParserJson().getNewsBlogData(page));

        }
    });

    return view;
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
    ((NavigationActivity) activity).onSectionAttached(
            getArguments().getInt(ARG_SECTION_NUMBER));
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}


@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    //FragmentManager fragmentManager = NavigationActivity.getSupportFragmentManager();
}

/**
 * The default content for this Fragment has a TextView that is shown when
 * the list is empty. If you would like to change the text, call this method
 * to supply the text it should use.
 */
public void setEmptyText(CharSequence emptyText) {
    View emptyView = mListView.getEmptyView();

    if (emptyView instanceof TextView) {
        ((TextView) emptyView).setText(emptyText);
    }
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p/>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    public void onNewsFragmentInteraction(String id);
}

}

这是我在 endless scroll list view 上找到的 EndlessScrollListener

public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 2;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 1;

public EndlessScrollListener() {
}

public EndlessScrollListener(int visibleThreshold) {
    this.visibleThreshold = visibleThreshold;
}

public EndlessScrollListener(int visibleThreshold, int startPage) {
    this.visibleThreshold = visibleThreshold;
    this.startingPageIndex = startPage;
    this.currentPage = startPage;
}

// This happens many times a second during a scroll, so be wary of the code
// you place here.
// We are given a few useful parameters to help us work out if we need to
// load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
                     int visibleItemCount, int totalItemCount) {
    // If the total item count is zero and the previous isn't, assume the
    // list is invalidated and should be reset back to initial state
    // If there are no items in the list, assume that initial items are
    // loading
    if (!loading && (totalItemCount < previousTotalItemCount)) {
        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) {
            this.loading = true;
        }
    }

    // If it’s still loading, we check to see if the dataset count has
    // changed, if so we conclude it has finished loading and update the
    // current page
    // number and total item count.
    if (loading) {
        if (totalItemCount > previousTotalItemCount) {
            loading = false;
            previousTotalItemCount = totalItemCount;
            currentPage++;
        }
    }

    // If it isn’t currently loading, we check to see if we have breached
    // the visibleThreshold and need to reload more data.
    // If we do need to reload some more data, we execute onLoadMore to
    // fetch the data.
    if (!loading
            && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
        onLoadMore(currentPage + 1, totalItemCount);
        loading = true;
    }
}

// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
    // Don't take any action on changed
}
}

请告诉我是否可以用其他方式完成整个事情,或者我应该附上其他代码或日志数据。

最佳答案

我在 stackoverflow 上找到了答案。现在我的 fragment 实现了 OnScrollListener 而不是创建单独的类。

我的代码是这样的

public class NewsFragment extends android.support.v4.app.Fragment implements
             AbsListView.OnItemClickListener, AbsListView.OnScrollListener {

private static final String ARG_SECTION_NUMBER = "section_number";
// Amount of items in the end of the list that should trigger the loading
private int threshold = 2;
// The index of the page from where I'm loading data
private int currentPage = 1;

// The list that is represented in the ListView
private ArrayList<NewsBlogData> newsData;

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
                     int visibleItemCount, int totalItemCount) {
    //leave this empty
}

@Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
    if (scrollState == SCROLL_STATE_IDLE) {
        if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) {
            currentPage++;
            //load more list items:
            newsData.addAll(new ParserJson().getNewsBlogData(currentPage));
            mAdapter.notifyDataSetChanged();
        }
    }
}

在这里找到这个答案 Android Endless List

仅添加

mAdapter.notifyDataSetChanged();

因为数据不是从主线程加载的。

可能它应该作为一个单独的类与 EndlessScrollListener 一起使用,但我没有测试它。

关于android - 无法通过无限滚动加载数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28073273/

相关文章:

Android房间数据库不会导出所有数据

Android:ViewPager从最后一页跳到第一页

java - Android 生命周期问题

javascript - 如何将嵌套的Rails ActiveRecord查询结果传递给gon?

java - fragment 中的 RecyclerView 在设备屏幕旋转时崩溃

Android - 从按钮中删除填充

c# - 解析复杂 json 字符串的最佳实践

java - 在 linux 的 java 文件中导入 json jar 时出错

java - 当 subview 可用时从父 fragment 调用子 fragment 方法?

java - Facebook 与fragment android 共享对话框