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

AsyncTaskLoader не запускается

Я хочу реализовать AsyncTaskLoader в своем проекте с помощью пакета Compatibility Package, поэтому я выполнил руководство Loader в Android Docs.

Проблема в том, что Loader ничего не делает, кажется, что loadInBackground() никогда не называется

Любая идея о том, что неправильно в моем коде? (ExpandableListFragment extends Fragment, но не переопределяет какой-либо критический метод)

Спасибо: -)

/** EDIT:

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

public class AgendaListFragment extends ExpandableListFragment implements
        LoaderManager.LoaderCallbacks<JSONArray> {

    private TreeMap<Integer, ArrayList<Evento>> mItems = new TreeMap<Integer, ArrayList<Evento>>();
    private AgendaListAdapter mAdapter;
    private ProgressBar mProgressBar;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_agenda, container);
        mProgressBar = (ProgressBar) root.findViewById(R.id.loading);
        return root;

    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mAdapter = new AgendaListAdapter(getActivity());
        setListAdapter(mAdapter);

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

    }

    @Override
    public Loader<JSONArray> onCreateLoader(int arg0, Bundle arg1) {
        mProgressBar.setVisibility(View.VISIBLE);
        return new AsyncTaskLoader<JSONArray>(getActivity()) {
            @Override
            public JSONArray loadInBackground() {

                return getDataFromService(AgendaServices.LISTADO_MES);

            }

        };
    }

    @Override
    public void onLoadFinished(Loader<JSONArray> loader, JSONArray data) {

        // Some stuff to turn JSONArray into TreeMap

        mProgressBar.setVisibility(View.GONE);
        mAdapter.setItems(mItems);

    }

    @Override
    public void onLoaderReset(Loader<JSONArray> arg0) {
        mAdapter.setItems(null);
        mProgressBar.setVisibility(View.VISIBLE);

    }

}
4b9b3361

Ответ 1

Я думаю, что лучшим решением для пакета Compatibility является переопределение метода AsyncTaskLoader.onStartLoading.

например.

@Override
protected void onStartLoading() {
  if(dataIsReady) {
    deliverResult(data);
  } else {
    forceLoad();
  }
}

Ответ 2

Это точно исправление, но оно должно работать. Я уверен, что библиотека совместимости нарушена. Попробуйте следующее:

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

Ответ 3

Cheok Yan Cheng абсолютно прав:

Проверка для takeContentChanged также является важным шагом.

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

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

Ответ 4

Глядя на обсуждение https://code.google.com/p/android/issues/detail?id=14944, проверка на takeContentChanged также является важным шагом.

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

Ответ 5

Я взял исходный код CursorLoader из фреймворка android и написал класс CustomTaskLoader<T>, чтобы облегчить работу.

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/android/content/CustomTaskLoader.java

вы в основном реализуете эти две функции:

public abstract T runTaskInBackground(CancellationSignal signal);
public abstract void cleanUp(T oldResult);

см. использование в действиях и фрагментах, например: (ну мой код просто игнорирует CancellationSignal, это a TODO в моем списке, но вы можете использовать его.)

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/PostListFragment.java

return new CustomTaskLoader<Cursor>(getActivity().getApplicationContext()) 
{
    @Override
    public Cursor runTaskInBackground(CancellationSignal signal)
    {
        return SiteSession.getAllPostsCursor(PostListAdapter.POST_COLUMNS);
    }

    @Override
    public void cleanUp(Cursor oldCursor)
    {
        if (!oldCursor.isClosed())
            oldCursor.close();
    }
}

Ответ 6

У меня была такая же проблема после перехода с CursorLoader на AsyncTaskLoader.

документация говорит: подклассы Loader<D> обычно должны реализовывать не менее onStartLoading(), onStopLoading(), onForceLoad(), и onReset().

AsyncTaskLoader расширяет Loader, но не реализует onStartLoading(), onStopLoading(), onReset(). Вы должны реализовать его самостоятельно!

@davidshen84 предложил хорошее решение. Я только добавил проверку для takeContentChanged.

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

        Log.d(TAG, "onStartLoading() ");
    } catch (Exception e) {
        Log.d(TAG, e.getMessage());
    }
}

Использование forceLoad() в порядке (не плохая практика). Посмотрите, какая документация говорит:
Обычно вы должны вызывать это только при запуске загрузчика - то есть isStarted() возвращает true.

Ответ 7

У меня все еще была проблема, что загрузка данных не вызывалась. Наконец, я удалил AsyncTaskLoader (версия библиотеки поддержки) и использовал только AsyncTask (не из библиотеки поддержки) для выполнения задания. И это сработало.

Этого может быть достаточно для ваших нужд.

Описание и пример: http://developer.android.com/reference/android/os/AsyncTask.html.

Вам нужно расширить класс AsyncTask.

Метод doInBackground выполнит работу, а в методе onPostExecute вы получите результат. Для запуска AsyncTask вы вызываете метод выполнить на свой экземпляр. См. Ссылку.