自定义加载器,用于无休止的滚动

时间:2014-05-07 16:56:26

标签: android android-listview android-asynctask loader

我正在尝试创建一个自定义加载器,它可以加载一个工作正常的数据列表,但现在我想在listview中添加无限滚动。我认为一个合理的位置将在加载器中,因为我在interwebz上看到的几乎所有示例都在自定义加载器中有一个私有字段,它对应于要返回给UI的数据,而在deliverResult中有一些像这样的代码

@Override
public void deliverResult(T data) {
    T oldData = mData;
    mData = data;
    if (isStarted()) {
        // If the loader is currently started, we can immediately deliver a result
        super.deliverResult(mData);
    }
}

不,我认为mData仍然包含前面的列表[1,2,3,4,5],因为加载器应该缓存数据以在配置更改时立即显示它。例如,数据是新的列表[6,7,8,9,10]。我只能将数据添加到mData,mData.add(数据),我们就完成了。不必在多个位置或不同的适配器上重复代码。但看起来这不起作用,每次调用restartLoader加载新数据时,框架都会创建一个新的Loader实例。有没有其他人遇到过这个问题?或者我应该在适配器中或代码中的其他位置执行mData.add(data)。

自定义加载器的完整实现,它扩展了ApiResponseLoader,也可以在下面找到:

public class SearchLoader extends ApiResponseLoader {

    private SearchType mSearchType;
    private int mOffset;
    private String mSearchQuery;


    public SearchLoader(Context context, SearchType type, int offset, String query) {
        super(context);
        mSearchType = type;
        mOffset = offset;
        mSearchQuery = query;
    }

    @Override
    public ApiResponse loadInBackground() {
        try {
            Map<String, String> parameters = Utils.parametersMap("q:" + mSearchQuery, "offset:" + String.valueOf(mOffset));
            return tryLoadInBackground(parameters);
        } catch (Exception e) {
            setError(e);
            return null;
        }
    }

    public ApiResponse tryLoadInBackground(Map<String, String> parameters) throws Exception {
        if (mSearchQuery == null) {
            throw new NullPointerException("mSearchQuery should not be null");
        }
        if (mSearchType == SearchType.A) {
            return RestAdapter().searchA(parameters);
        } else {
            return RestAdapter().searchB(parameters);
        }
    }
}

public abstract class ApiResponseLoader extends AsyncTaskLoader<ApiResponse> {
    private final static String TAG = ApiResponseLoader.class.getSimpleName();
    private ApiResponse mApiResponse;
    private Exception mError;

    public ApiResponseLoader(Context context) {
        super(context);
    }

    public abstract ApiResponse tryLoadInBackground(Map<String, String> parameters) throws Exception;

    @Override
    protected void onStartLoading() {
        if (mApiResponse != null) {
            deliverResult(mApiResponse);
        }
        if (takeContentChanged() || mApiResponse == null) {
            forceLoad();
        }
    }

    @Override
    protected void onForceLoad() {
        super.onForceLoad();
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    public void onCanceled(ApiResponse data) {
        // Attempt to cancel the current asynchronous load.
        super.onCanceled(data);
    }

    @Override
    protected void onReset() {
        // Ensure the loader has been stopped.
        onStopLoading();

        // At this point we can release the resources associated with 'apps' if needed
        if (mApiResponse != null) {
            mApiResponse = null;
        }
    }

    @Override
    public void deliverResult(ApiResponse data) {
        if (isReset()) {
            // An async query came in while the loader is stopped. We don't need the result
            if (data != null) {
                onReleaseResources(data);
            }
            return;
        }
        if (mApiResponse != null) {
            mApiResponse.mMeta = data.mMeta;
            mApiResponse.mSampleList.addAll(data.mSampleList);
        } else {
            mApiResponse = data;
        }

        if (isStarted()) {
            // If the loader is currently started, we can immediately deliver a result
            super.deliverResult(mApiResponse);
        }
    }

    public Exception getError() {
        return mError;
    }

    public void setError(Exception mError) {
        this.mError = mError;
    }
}

0 个答案:

没有答案