Подтвердить что ты не робот

Android AsyncTaskLoader не запускает loadInBackground?

Я пытаюсь реализовать пример загрузчика на Android, но не могу заставить его запустить загрузчик. Я использую следующий код. Он попадет в "Create Loader", но он никогда не достигнет сообщения журнала "Загрузка начата". Мне не хватает звонка, который мне нужен?

Активность:

    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);
        }
    }

Погрузчик:

    public class ImageLoader extends AsyncTaskLoader<ArrayList<Content>> {

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

        @Override
        public ArrayList<Content> loadInBackground() {
            Log.e("TEST", "Loading started");
        }

    }
4b9b3361

Ответ 1

У меня была такая же проблема с использованием библиотеки совместимости. Я решил это, позвонив forceLoad

getLoaderManager().initLoader(0, null, this).forceLoad();

Очевидно, что документация по AsyncLoader отсутствует, и эта проблема также существует в HoneyComb. Более подробную информацию можно найти здесь

Официальный пример AsyncTaskLoader также вызывает forceLoad(), поэтому он не является ошибкой, но я все же считаю, что это поведение не очень интуитивное.

Ответ 2

Переопределить loadInBackground() недостаточно.

Посмотрите AppListLoader на http://developer.android.com/reference/android/content/AsyncTaskLoader.html.

По крайней мере, добавьте эти два метода в ваш загрузчик:

        @Override
        protected void onStartLoading() {
            if (takeContentChanged())
                forceLoad();
        }

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

и вызовите onContentChanged() из своего конструктора.

Ответ 3

rrayst советы довольно компактны. Если вы напишете свой метод следующим образом:

protected void onStartLoading() {
    forceLoad();
}

вы заметите, что при появлении дочерней активности, а затем вы вернетесь к родительскому, onStartLoading (и так loadInBackground) снова вызываются!

Что вы можете сделать? Установите внутреннюю переменную (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 how we start every AsyncTaskLoader...
        // -  code snippet from  android.content.CursorLoader  (method  onStartLoading)
        if (takeContentChanged()) {
            forceLoad();
        }
    }

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

Ответ 4

Поскольку ни один из ответов здесь (кроме принятого) не помог мне решить это, вот как это сработало для меня.

Я не думаю, что принятый ответ является правильным решением, так как он вызывает 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

Если вы используете пользовательский загрузчик, вы можете сохранить последнюю ссылку на данные и получить ее через геттер. когда пользователь поворачивает свой экран, вы можете вернуть загрузчика из метода getLoaderManager(). getLoader, а затем вернуть ссылку. Для моего тестирования я заметил, что startLoadering доходит до CustomLoader.onLoadFinished, но результат никогда не доставляется в activity.onLoadFinished. Я подозреваю, что ссылка на активность теряется при ротации. Кстати, великое дело в создании загрузчиков - они упорны через LoaderManager. Подумайте об этом как о другом аромате безголовых обломков.. lol.

Loader loader  =  getLoaderManager().getLoader(LOADER_ID);

if( loader == null )
{
    getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
    listAdapter.addAll(((CustomLoader) loader).getLastData());
}

Ответ 6

Я обнаружил, что каждое из вышеперечисленных решений имеет проблемы, особенно когда приложение запускается, когда экран выключен, а загрузка занимает несколько секунд.

Здесь мое решение (база this):

public abstract class AsyncTaskLoaderEx<T> extends AsyncTaskLoader<T> {
    private static final AtomicInteger sCurrentUniqueId = new AtomicInteger(0);
    private T mData;
    public boolean hasResult = false;

    public static int getNewUniqueLoaderId() {
        return sCurrentUniqueId.getAndIncrement();
    }

    public AsyncTaskLoaderEx(final Context context) {
        super(context);
        onContentChanged();
    }

    @Override
    protected void onStartLoading() {
        if (takeContentChanged())
            forceLoad();
        else if (hasResult)
            deliverResult(mData);
    }

    @Override
    public void deliverResult(final T data) {
        mData = data;
        hasResult = true;
        super.deliverResult(data);
    }

    @Override
    protected void onReset() {
        super.onReset();
        onStopLoading();
        if (hasResult) {
            onReleaseResources(mData);
            mData = null;
            hasResult = false;
        }
    }

    protected void onReleaseResources(T data) {
        //nothing to do.
    }

    public T getResult() {
        return mData;
    }
}