web-dev-qa-db-ja.com

AsyncTaskLoaderが実行されない

互換性パッケージを使用してプロジェクトにAsyncTaskLoaderを実装したいので、Android Docs)のローダーのマニュアルに従いました。

問題は、ローダーが何もしないことです。loadInBackground()が呼び出されることはないようです。

私のコードの何が問題になっているのか考えていますか? (ExpandableListFragmentFragmentを拡張しますが、重要なメソッドをオーバーライドしません)

ありがとうございました :-)

/ **編集:

私は(遅く、私はモロンです)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);

    }

}
30
Aitor Gómez

互換性パッケージの最善の解決策は、AsyncTaskLoader.onStartLoadingメソッドをオーバーライドすることだと思います。

例えば.

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

これは正確に修正されていますが、機能するはずです。互換性ライブラリが壊れていると確信しています。これを試して:

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

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's how we start every AsyncTaskLoader...
        // -  code snippet from  Android.content.CursorLoader  (method  onStartLoading)
        if (takeContentChanged()) {
            forceLoad();
        }
    }
}
3
KitKat

https://code.google.com/p/Android/issues/detail?id=14944 でのディスカッションを見ると、takeContentChangedをチェックすることも重要なステップのようです。

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

AndroidフレームワークからCursorLoaderのソースコードを取得し、作業を容易にするためにCustomTaskLoader<T>クラスを作成しました。

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

基本的に、次の2つの関数を実装します。

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

アクティビティとフラグメントでの使用法を参照してください。たとえば、次のようになります(私のコードはCancellationSignalを無視します。これは、私のリストでは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();
    }
}
0
曾其威

CursorLoaderからAsyncTaskLoaderに移行した後、同じ問題が発生しました。

ドキュメントによるとLoader<D>のサブクラスは、通常、少なくともonStartLoading()、onStopLoading()、onForceLoad()、およびonReset()

AsyncTaskLoaderはローダーを拡張しますが、実装しません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を返します。

0
Yuliia Ashomok