当用户向下滚动时,自动将新条目从服务器加载到ScrollView

时间:2016-01-19 04:17:58

标签: java android scrollview android-scrollview

让我简要解释一下我的活动结构。当用户输入应用程序时,它们会立即发送到显示ScrollView的片段,其中包含一系列布局。布局由从服务器提取的数据填充,前十个左右加载了片段的创建。当用户向下滚动ScrollView时,我希望将新布局添加到ScrollView的底部,这样就不必立即从服务器收集所有数据,因此条目列表不会超过它需要的大小。

这方面的一个例子是Facebook的Android应用程序的新闻源,或Instagram的滚动图片。 Gmail应用也会出现此行为,并根据需要加载电子邮件。在所有情况下,当用户向下滚动页面时,将加载新数据。

我的问题是,这种行为的实施效果如何?

我最好定义为:

  • 最有效率的
  • 最便携(功能最多的手机和大多数API版本)
  • 最容易维护和扩展
  • 遵循公认的Android标准和惯例

要明确,我不仅仅是在寻找 解决方案,而是最好的解决方案。我知道有多种方法可以实现这种行为,但我正在寻找一个明确的解决方案。请提供几句话来解释为什么您的方法是最好的。谢谢。

2 个答案:

答案 0 :(得分:0)

您可以使用此类从服务器加载更多项目

公共类LoadMoreListView扩展了ListView实现的OnScrollListener {

private static final String TAG = "LoadMoreListView";

/**
 * Listener that will receive notifications every time the list scrolls.
 */
private OnScrollListener mOnScrollListener;
private LayoutInflater mInflater;

// footer view
private RelativeLayout mFooterView;
// private TextView mLabLoadMore;
private ProgressBar mProgressBarLoadMore;

// Listener to process load more items when user reaches the end of the list
private OnLoadMoreListener mOnLoadMoreListener;
// To know if the list is loading more items
private boolean mIsLoadingMore = false;
private int mCurrentScrollState;

public LoadMoreListView(Context context) {
    super(context);
    init(context);
}

public LoadMoreListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public LoadMoreListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context) {

    mInflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // footer
    mFooterView = (RelativeLayout) mInflater.inflate(
            R.layout.load_more_footer, this, false);
    /*
     * mLabLoadMore = (TextView) mFooterView
     * .findViewById(R.id.load_more_lab_view);
     */
    mProgressBarLoadMore = (ProgressBar) mFooterView
            .findViewById(R.id.load_more_progressBar);

    addFooterView(mFooterView);

    super.setOnScrollListener(this);
}

@Override
public void setAdapter(ListAdapter adapter) {
    super.setAdapter(adapter);
}

/**
 * Set the listener that will receive notifications every time the list
 * scrolls.
 * 
 * @param l
 *            The scroll listener.
 */
@Override
public void setOnScrollListener(AbsListView.OnScrollListener l) {
    mOnScrollListener = l;
}

/**
 * Register a callback to be invoked when this list reaches the end (last
 * item be visible)
 * 
 * @param onLoadMoreListener
 *            The callback to run.
 */

public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
    mOnLoadMoreListener = onLoadMoreListener;
}

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

    if (mOnScrollListener != null) {
        mOnScrollListener.onScroll(view, firstVisibleItem,
                visibleItemCount, totalItemCount);
    }

    if (mOnLoadMoreListener != null) {

        if (visibleItemCount == totalItemCount) {
            mProgressBarLoadMore.setVisibility(View.GONE);
            // mLabLoadMore.setVisibility(View.GONE);
            return;
        }

        boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;

        if (!mIsLoadingMore && loadMore
                && mCurrentScrollState != SCROLL_STATE_IDLE) {
            mProgressBarLoadMore.setVisibility(View.VISIBLE);
            // mLabLoadMore.setVisibility(View.VISIBLE);
            mIsLoadingMore = true;
            onLoadMore();
        }

    }

}

public void onScrollStateChanged(AbsListView view, int scrollState) {

    // bug fix: listview was not clickable after scroll
    if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
        view.invalidateViews();
    }

    mCurrentScrollState = scrollState;

    if (mOnScrollListener != null) {
        mOnScrollListener.onScrollStateChanged(view, scrollState);
    }

}

public void onLoadMore() {
    Log.d(TAG, "onLoadMore");
    if (mOnLoadMoreListener != null) {
        mOnLoadMoreListener.onLoadMore();
    }
}

/**
 * Notify the loading more operation has finished
 */
public void onLoadMoreComplete() {
    mIsLoadingMore = false;
    mProgressBarLoadMore.setVisibility(View.GONE);
}

/**
 * Interface definition for a callback to be invoked when list reaches the
 * last item (the user load more items in the list)
 */
public interface OnLoadMoreListener {
    /**
     * Called when the list reaches the last item (the last item is visible
     * to the user)
     */
    public void onLoadMore();
}

}

这是用于从server加载更多项的自定义List视图。你应该使用LoadMoreListView类来完成这项工作。你可以像这样在xml中调用这个类

     <com.broadpeak.nvoice.utils.LoadMoreListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

lmlv = (LoadMoreListView) view.findViewById(R.id.lv);
    lmlv.setOnLoadMoreListener(new OnLoadMoreListener() {

        @Override
        public void onLoadMore() {

         }
    });

如果有任何查询,那么您可以自由联系....

答案 1 :(得分:0)

您尝试使用的方法称为 LazyLoading 作为Android开发中的建议方式,您可以使用recycler viewsRecyclerAdapter来实现此目的。

首先定义Recycler适配器和视图  然后,您可以将onScrollListener设置为回收适配器,它应该像(Original Source)

public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
    public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();

    private int previousTotal = 0; // The total number of items in the dataset after the last load
    private boolean loading = true; // True if we are still waiting for the last set of data to load.
    private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int current_page = 1;

    private LinearLayoutManager mLinearLayoutManager;

    public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
        this.mLinearLayoutManager = linearLayoutManager;
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount)
                <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached

            // Do something
            // like Load from server
            current_page++;

            onLoadMore(current_page);

            loading = true;
        }
    }

    public abstract void onLoadMore(int current_page);
}

正如您所看到的那样,您可以使用onScrolled方法发出服务器请求,我认为您可以使用 RetroFit okHttp