AsyncTaskLoader 在方向改变后不调用 onFinishedLoad
AsyncTaskLoader not calling onFinishedLoad after orientation change
一些背景信息:
我正在使用 Activity>ParentFragment(Holds ViewPager)>Child 片段。
使用添加、删除按钮动态添加子片段。
我正在使用 MVP 架构
实际问题:
在子片段中,我们有列表视图,它通过演示者使用 asynctaskloader 进行填充。
子片段:
//Initialize Views
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_search_view_child, container, false);
.......
mSearchViewPresenter= new SearchViewPresenter(
getActivity(),
new GoogleSuggestLoader(getContext()),
getActivity().getLoaderManager(),
this, id
);
SearchList list=new SearchList();
//requestList from presenter
searchListAdapter =new SearchViewListAdapter(getActivity(), list, this);
listView.setAdapter(searchListAdapter);
......
return root;
}
@Override
public void onResume(){
super.onResume();
mSearchViewPresenter.start();
searchBar.addTextChangedListener(textWatcher);
}
在演示者中 class 我们有:
public SearchViewPresenter(@NonNull Context context, @NonNull GoogleSuggestLoader googleloader,@NonNull LoaderManager loaderManager,
@NonNull SearchViewContract.View tasksView, @NonNull String id) {
// mLoader = checkNotNull(loader, "loader cannot be null!");
mLoaderManager = checkNotNull(loaderManager, "loader manager cannot be null");
// mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
mSearchView = checkNotNull(tasksView, "tasksView cannot be null!");
mSearchView.setPresenter(this);
searchList=new SearchList();
this.googleLoader=googleloader;
this.context=context;
this.id=loaderID;
// this.id=Integer.parseInt(id);
}
@Override
public void start() {
Log.d("start>initloader","log");
mLoaderManager.restartLoader(1, null, this);
}
//TODO implement these when you are ready to use loader to cache local browsing history
@Override
public android.content.Loader<List<String>> onCreateLoader(int i, Bundle bundle) {
int loaderid=googleLoader.getId();
Log.d("Loader: ", "created");
googleLoader=new GoogleSuggestLoader(context);
googleLoader.setUrl("");
googleLoader.setUrl(mSearchView.provideTextQuery());
return googleLoader;
}
@Override
public void onLoadFinished(android.content.Loader<List<String>> loader, List<String> data) {
Log.d("Loader: ", "loadFinished");
searchList.clear();
for (int i = 0; i < data.size(); ++i) {
searchList.addListItem(data.get(i), null, LIST_TYPE_SEARCH, android.R.drawable.btn_plus);
Log.d("data Entry: ",i+ " is: "+searchList.getText(i));
}
mSearchView.updateSearchList(searchList);
}
@Override
public void onLoaderReset(android.content.Loader<List<String>> loader) {
}
我们在演示者中也有这段代码,由正在编辑的片段视图上的编辑文本框触发。
@Override
public void notifyTextEntry() {
//DETERMINE HOW TO GIVE LIST HERE
// Dummy List
Log.d("notifyTextEntry","log");
if(googleLoader==null)googleLoader=new GoogleSuggestLoader(context);
googleLoader.setUrl(mSearchView.provideTextQuery());
// mLoaderManager.getLoader(id).abandon();
mLoaderManager.getLoader(1).forceLoad();
mLoaderManager.getLoader(1).onContentChanged();
Log.d("length ", searchList.length().toString());
// googleLoader.onContentChanged();
}
最后我们有加载程序:
public class GoogleSuggestLoader extends AsyncTaskLoader<List<String>>{
/** Query URL */
private String mUrl;
private static final String BASE_URL="https://suggestqueries.google.com/complete/search?client=firefox&oe=utf-8&q=";
private List<String> suggestions =new ArrayList<>();
public GoogleSuggestLoader(Context context) {
super(context);
this.mUrl=BASE_URL;
}
public void setUrl(String mUrl){
this.mUrl=BASE_URL+mUrl;
};
@Override
protected void onStartLoading() {forceLoad(); }
@Override
public List<String> loadInBackground() {
if (mUrl == null) {
return null;
}
try {
suggestions = new ArrayList<>();
Log.d("notifyinsideLoader","log");
String result=GoogleSuggestParser.parseTemp(mUrl);
if(result!=null) {
JSONArray json = new JSONArray(result);
if (json != null) {
JSONArray inner=new JSONArray((json.getString(1)));
if(inner!=null){
for (int i = 0; i < inner.length(); ++i) {
//only show 3 results
if(i==3)break;
Log.d("notifyinsideLoader",inner.getString(i));
suggestions.add(inner.getString(i));
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return suggestions;
}
}
所以问题:
代码将数据很好地加载到片段的列表视图中。当方向改变时,加载程序不会调用 onLoadFinished。我已经测试了加载程序,它正在很好地处理数据。
我已经在演示者中尝试了 forceload 和 onContentChanged 无济于事。
如果您需要更多信息,或者我是否应该使用其他类似 RxJava 的东西,请告诉我。但我真的很想让这个工作。
在您提问之前,我已经看到类似的问题,例如:AsyncTaskLoader: onLoadFinished not called after orientation change 但是我使用的是相同的 ID,所以这个问题不应该存在。
答案在此页上 AsyncTaskLoader doesn't call onLoadFinished
但没有详细说明如何转向这一点。
所以让我在这里为以后遇到此问题的其他人解释一下。
支持库适用于片段。因此,负责 回调 的 class 必须从支持库中导入并实施正确的方法。就像您使用 MVP 一样,您的演示者必须从支持 loadermanager 扩展。
即:导入 android.support.v4.app.LoaderManager;然后实现正确的回调。
喜欢
@Override
public android.support.v4.content.Loader<List<String>> onCreateLoader(int i, Bundle bundle) {
...
return new loader
}
和
@Override
public void onLoadFinished(android.support.v4.content.Loader<List<String>> loader, List<String> data) {
//do something here to your UI with data
}
其次:加载器本身必须从支持 asynctaskloader 扩展。
即:导入 android.support.v4.content.AsyncTaskLoader;
一些背景信息: 我正在使用 Activity>ParentFragment(Holds ViewPager)>Child 片段。 使用添加、删除按钮动态添加子片段。 我正在使用 MVP 架构
实际问题: 在子片段中,我们有列表视图,它通过演示者使用 asynctaskloader 进行填充。
子片段:
//Initialize Views
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_search_view_child, container, false);
.......
mSearchViewPresenter= new SearchViewPresenter(
getActivity(),
new GoogleSuggestLoader(getContext()),
getActivity().getLoaderManager(),
this, id
);
SearchList list=new SearchList();
//requestList from presenter
searchListAdapter =new SearchViewListAdapter(getActivity(), list, this);
listView.setAdapter(searchListAdapter);
......
return root;
}
@Override
public void onResume(){
super.onResume();
mSearchViewPresenter.start();
searchBar.addTextChangedListener(textWatcher);
}
在演示者中 class 我们有:
public SearchViewPresenter(@NonNull Context context, @NonNull GoogleSuggestLoader googleloader,@NonNull LoaderManager loaderManager,
@NonNull SearchViewContract.View tasksView, @NonNull String id) {
// mLoader = checkNotNull(loader, "loader cannot be null!");
mLoaderManager = checkNotNull(loaderManager, "loader manager cannot be null");
// mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
mSearchView = checkNotNull(tasksView, "tasksView cannot be null!");
mSearchView.setPresenter(this);
searchList=new SearchList();
this.googleLoader=googleloader;
this.context=context;
this.id=loaderID;
// this.id=Integer.parseInt(id);
}
@Override
public void start() {
Log.d("start>initloader","log");
mLoaderManager.restartLoader(1, null, this);
}
//TODO implement these when you are ready to use loader to cache local browsing history
@Override
public android.content.Loader<List<String>> onCreateLoader(int i, Bundle bundle) {
int loaderid=googleLoader.getId();
Log.d("Loader: ", "created");
googleLoader=new GoogleSuggestLoader(context);
googleLoader.setUrl("");
googleLoader.setUrl(mSearchView.provideTextQuery());
return googleLoader;
}
@Override
public void onLoadFinished(android.content.Loader<List<String>> loader, List<String> data) {
Log.d("Loader: ", "loadFinished");
searchList.clear();
for (int i = 0; i < data.size(); ++i) {
searchList.addListItem(data.get(i), null, LIST_TYPE_SEARCH, android.R.drawable.btn_plus);
Log.d("data Entry: ",i+ " is: "+searchList.getText(i));
}
mSearchView.updateSearchList(searchList);
}
@Override
public void onLoaderReset(android.content.Loader<List<String>> loader) {
}
我们在演示者中也有这段代码,由正在编辑的片段视图上的编辑文本框触发。
@Override
public void notifyTextEntry() {
//DETERMINE HOW TO GIVE LIST HERE
// Dummy List
Log.d("notifyTextEntry","log");
if(googleLoader==null)googleLoader=new GoogleSuggestLoader(context);
googleLoader.setUrl(mSearchView.provideTextQuery());
// mLoaderManager.getLoader(id).abandon();
mLoaderManager.getLoader(1).forceLoad();
mLoaderManager.getLoader(1).onContentChanged();
Log.d("length ", searchList.length().toString());
// googleLoader.onContentChanged();
}
最后我们有加载程序:
public class GoogleSuggestLoader extends AsyncTaskLoader<List<String>>{
/** Query URL */
private String mUrl;
private static final String BASE_URL="https://suggestqueries.google.com/complete/search?client=firefox&oe=utf-8&q=";
private List<String> suggestions =new ArrayList<>();
public GoogleSuggestLoader(Context context) {
super(context);
this.mUrl=BASE_URL;
}
public void setUrl(String mUrl){
this.mUrl=BASE_URL+mUrl;
};
@Override
protected void onStartLoading() {forceLoad(); }
@Override
public List<String> loadInBackground() {
if (mUrl == null) {
return null;
}
try {
suggestions = new ArrayList<>();
Log.d("notifyinsideLoader","log");
String result=GoogleSuggestParser.parseTemp(mUrl);
if(result!=null) {
JSONArray json = new JSONArray(result);
if (json != null) {
JSONArray inner=new JSONArray((json.getString(1)));
if(inner!=null){
for (int i = 0; i < inner.length(); ++i) {
//only show 3 results
if(i==3)break;
Log.d("notifyinsideLoader",inner.getString(i));
suggestions.add(inner.getString(i));
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return suggestions;
}
}
所以问题:
代码将数据很好地加载到片段的列表视图中。当方向改变时,加载程序不会调用 onLoadFinished。我已经测试了加载程序,它正在很好地处理数据。 我已经在演示者中尝试了 forceload 和 onContentChanged 无济于事。 如果您需要更多信息,或者我是否应该使用其他类似 RxJava 的东西,请告诉我。但我真的很想让这个工作。 在您提问之前,我已经看到类似的问题,例如:AsyncTaskLoader: onLoadFinished not called after orientation change 但是我使用的是相同的 ID,所以这个问题不应该存在。
答案在此页上 AsyncTaskLoader doesn't call onLoadFinished 但没有详细说明如何转向这一点。 所以让我在这里为以后遇到此问题的其他人解释一下。
支持库适用于片段。因此,负责 回调 的 class 必须从支持库中导入并实施正确的方法。就像您使用 MVP 一样,您的演示者必须从支持 loadermanager 扩展。 即:导入 android.support.v4.app.LoaderManager;然后实现正确的回调。
喜欢
@Override
public android.support.v4.content.Loader<List<String>> onCreateLoader(int i, Bundle bundle) {
...
return new loader
}
和
@Override
public void onLoadFinished(android.support.v4.content.Loader<List<String>> loader, List<String> data) {
//do something here to your UI with data
}
其次:加载器本身必须从支持 asynctaskloader 扩展。 即:导入 android.support.v4.content.AsyncTaskLoader;