我正在尝试创建一个自定义加载器,它可以加载一个工作正常的数据列表,但现在我想在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;
}
}