I am trying to implement a loader example on Android but can't get it to start the loader. I am using the following code. It will hit the "Create Loader" but it will never reach the "Loading started" log message. Am I missing a call that I need?
我正在尝试在Android上实现一个加载程序示例,但是无法让它启动加载程序。我正在使用下面的代码。它将击中“创建加载程序”,但它永远不会到达“加载启动”日志消息。我是不是错过了一个我需要的电话?
Activity:
活动:
public class TestingZoneActivity extends ListActivity implements LoaderCallbacks<ArrayList<Content>>{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<ArrayList<Content>> onCreateLoader(int id, Bundle args) {
Log.e("TEST", "Create Loader");
return new ImageLoader(this);
}
@Override
public void onLoadFinished(Loader<ArrayList<Content>> loader, ArrayList<Content> data) {
setListAdapter(new ImageAdapter(this, data));
}
@Override
public void onLoaderReset(Loader<ArrayList<Content>> loader) {
setListAdapter(null);
}
}
Loader:
加载程序:
public class ImageLoader extends AsyncTaskLoader<ArrayList<Content>> {
public ImageLoader(Context context) {
super(context);
}
@Override
public ArrayList<Content> loadInBackground() {
Log.e("TEST", "Loading started");
}
}
6 个解决方案
#1
123
I had the same problem using the compatibility library. I solved it by calling forceLoad
我在使用兼容性库时遇到了同样的问题。我通过调用forceLoad解决了这个问题
getLoaderManager().initLoader(0, null, this).forceLoad();
Obviously the documentation on AsyncLoader is lacking and this problem also exists on HoneyComb. More information can be found here
显然,关于异步读写器的文档是缺乏的,这个问题也存在于蜂巢中。更多信息可以在这里找到
The official example of AsyncTaskLoader is also calling forceLoad() so its not a bug, but i still think that that behavior is not very intuitive.
AsyncTaskLoader的官方示例也调用forceLoad(),所以它不是一个bug,但是我仍然认为这种行为不是很直观。
#2
23
Overriding loadInBackground()
is not enough.
重写loadInBackground()是不够的。
Have a look at the AppListLoader
on http://developer.android.com/reference/android/content/AsyncTaskLoader.html .
在http://developer.android.com/reference/android/content/AsyncTaskLoader.html中查看AppListLoader。
At least add these two methods to your loader:
至少将这两种方法添加到加载程序中:
@Override
protected void onStartLoading() {
if (takeContentChanged())
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
and call onContentChanged()
from its constructor.
并从其构造函数调用onContentChanged()。
#3
12
rrayst's advice is quite compact. If you write your method like this:
rrayst的建议非常简洁。如果你这样写你的方法:
protected void onStartLoading() {
forceLoad();
}
you ''ll notice that when a child activity comes up and then you return to the parent one, onStartLoading
(and so loadInBackground
) are called again!
您将注意到,当出现子活动并返回到父活动时,将再次调用onStartLoading(和so loadInBackground) !
What can you do? Set an internal variable (mContentChanged
) to true inside the constructor; then check this variable inside onStartLoading
. Only when it's true, start loading for real:
你会做什么呢?将构造函数内部变量(mContentChanged)设置为true;然后在onStartLoading中检查这个变量。只有当它为真时,才开始为真:
package example.util;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public abstract class ATLoader<D> extends AsyncTaskLoader<D> {
public ATLoader(Context context) {
super(context);
// run only once
onContentChanged();
}
@Override
protected void onStartLoading() {
// That's how we start every AsyncTaskLoader...
// - code snippet from android.content.CursorLoader (method onStartLoading)
if (takeContentChanged()) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
}
#4
2
Since none of the answers here (besides the accepted one) alone helped me to solve this, here is how it worked for me.
由于这里没有一个答案(除了公认的答案)能帮助我解决这个问题,下面是它对我的作用。
I don't think the accepted answer is the correct solution, since it causes loadInBackground()
to be called more often than necessary, i.e. on orientation change, which does not happen when properly overriding the following methods in the loader as well:
我不认为所接受的答案是正确的解决方案,因为它使loadInBackground()被调用的频率超过了必要的频率,也就是说,在方向改变时,当正确地覆盖加载器中的以下方法时,也不会发生这种情况:
@Override
public void deliverResult(final List<Participant> data) {
participants = data;
if (isStarted()) {
super.deliverResult(data);
}
}
@Override
protected void onStartLoading() {
if (takeContentChanged() || participants == null) {
forceLoad();
}
}
#5
0
If you are using a custom loader, you can save the last data reference, and have it available via a getter. when the user rotates his screen, you can get the loader back from getLoaderManager().getLoader method, and then return back the reference. For my testing I noticed that startLoadering goes all the way to CustomLoader.onLoadFinished but the result is never deliver to activity.onLoadFinished.I suspect the activity reference gets lost upon rotation. By the way the great thing about creating loaders is they are persistent through LoaderManager. Think of it as another flavor of headless fragments.. lol.
如果您正在使用自定义加载程序,您可以保存最后的数据引用,并通过getter使其可用。当用户旋转他的屏幕时,您可以从getLoaderManager()返回加载器。getLoader方法,然后返回引用。在我的测试中,我注意到startLoadering一直到CustomLoader。onLoadFinished, but the result is never deliver to activity.onLoadFinished。我怀疑活动引用在旋转时丢失。顺便说一下,创建装入器的好处是它们通过LoaderManager是持久性的。把它想象成另一种无头碎片的味道。哈哈
Loader loader = getLoaderManager().getLoader(LOADER_ID);
if( loader == null )
{
getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
listAdapter.addAll(((CustomLoader) loader).getLastData());
}
#6
0
I've found that each of the above solutions have issues, especially when the app starts while the screen is turned off, and the loading takes a few moments.
我发现上面的每个解决方案都有问题,特别是当应用程序启动时,屏幕被关闭,加载需要一些时间。
Here's my solution (base on this):
以下是我的解决方案(基于此):
https://*.com/a/22675607/878126
https://*.com/a/22675607/878126
#1
123
I had the same problem using the compatibility library. I solved it by calling forceLoad
我在使用兼容性库时遇到了同样的问题。我通过调用forceLoad解决了这个问题
getLoaderManager().initLoader(0, null, this).forceLoad();
Obviously the documentation on AsyncLoader is lacking and this problem also exists on HoneyComb. More information can be found here
显然,关于异步读写器的文档是缺乏的,这个问题也存在于蜂巢中。更多信息可以在这里找到
The official example of AsyncTaskLoader is also calling forceLoad() so its not a bug, but i still think that that behavior is not very intuitive.
AsyncTaskLoader的官方示例也调用forceLoad(),所以它不是一个bug,但是我仍然认为这种行为不是很直观。
#2
23
Overriding loadInBackground()
is not enough.
重写loadInBackground()是不够的。
Have a look at the AppListLoader
on http://developer.android.com/reference/android/content/AsyncTaskLoader.html .
在http://developer.android.com/reference/android/content/AsyncTaskLoader.html中查看AppListLoader。
At least add these two methods to your loader:
至少将这两种方法添加到加载程序中:
@Override
protected void onStartLoading() {
if (takeContentChanged())
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
and call onContentChanged()
from its constructor.
并从其构造函数调用onContentChanged()。
#3
12
rrayst's advice is quite compact. If you write your method like this:
rrayst的建议非常简洁。如果你这样写你的方法:
protected void onStartLoading() {
forceLoad();
}
you ''ll notice that when a child activity comes up and then you return to the parent one, onStartLoading
(and so loadInBackground
) are called again!
您将注意到,当出现子活动并返回到父活动时,将再次调用onStartLoading(和so loadInBackground) !
What can you do? Set an internal variable (mContentChanged
) to true inside the constructor; then check this variable inside onStartLoading
. Only when it's true, start loading for real:
你会做什么呢?将构造函数内部变量(mContentChanged)设置为true;然后在onStartLoading中检查这个变量。只有当它为真时,才开始为真:
package example.util;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public abstract class ATLoader<D> extends AsyncTaskLoader<D> {
public ATLoader(Context context) {
super(context);
// run only once
onContentChanged();
}
@Override
protected void onStartLoading() {
// That's how we start every AsyncTaskLoader...
// - code snippet from android.content.CursorLoader (method onStartLoading)
if (takeContentChanged()) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
}
#4
2
Since none of the answers here (besides the accepted one) alone helped me to solve this, here is how it worked for me.
由于这里没有一个答案(除了公认的答案)能帮助我解决这个问题,下面是它对我的作用。
I don't think the accepted answer is the correct solution, since it causes loadInBackground()
to be called more often than necessary, i.e. on orientation change, which does not happen when properly overriding the following methods in the loader as well:
我不认为所接受的答案是正确的解决方案,因为它使loadInBackground()被调用的频率超过了必要的频率,也就是说,在方向改变时,当正确地覆盖加载器中的以下方法时,也不会发生这种情况:
@Override
public void deliverResult(final List<Participant> data) {
participants = data;
if (isStarted()) {
super.deliverResult(data);
}
}
@Override
protected void onStartLoading() {
if (takeContentChanged() || participants == null) {
forceLoad();
}
}
#5
0
If you are using a custom loader, you can save the last data reference, and have it available via a getter. when the user rotates his screen, you can get the loader back from getLoaderManager().getLoader method, and then return back the reference. For my testing I noticed that startLoadering goes all the way to CustomLoader.onLoadFinished but the result is never deliver to activity.onLoadFinished.I suspect the activity reference gets lost upon rotation. By the way the great thing about creating loaders is they are persistent through LoaderManager. Think of it as another flavor of headless fragments.. lol.
如果您正在使用自定义加载程序,您可以保存最后的数据引用,并通过getter使其可用。当用户旋转他的屏幕时,您可以从getLoaderManager()返回加载器。getLoader方法,然后返回引用。在我的测试中,我注意到startLoadering一直到CustomLoader。onLoadFinished, but the result is never deliver to activity.onLoadFinished。我怀疑活动引用在旋转时丢失。顺便说一下,创建装入器的好处是它们通过LoaderManager是持久性的。把它想象成另一种无头碎片的味道。哈哈
Loader loader = getLoaderManager().getLoader(LOADER_ID);
if( loader == null )
{
getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
listAdapter.addAll(((CustomLoader) loader).getLastData());
}
#6
0
I've found that each of the above solutions have issues, especially when the app starts while the screen is turned off, and the loading takes a few moments.
我发现上面的每个解决方案都有问题,特别是当应用程序启动时,屏幕被关闭,加载需要一些时间。
Here's my solution (base on this):
以下是我的解决方案(基于此):
https://*.com/a/22675607/878126
https://*.com/a/22675607/878126