30

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

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

私のコードで何が問題なのか分かりますか? (ExpandableListFragment拡張Fragmentしますが、重要なメソッドをオーバーライドしません)

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

/**編集:

AsyncTaskLoader は抽象クラスなので、サブクラス化する必要があることに気付きました (遅れて、私はばかです)。

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

    }

}
4

7 に答える 7

63

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

例えば

@Override
protected void onStartLoading() {
  if(dataIsReady) {
    deliverResult(data);
  } else {
    forceLoad();
  }
}
于 2012-01-12T05:55:47.310 に答える
8

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

getLoaderManager().initLoader(0, null, this).forceLoad();
于 2011-12-27T00:40:42.817 に答える
3

Cheok Yan Chengは完全に正しいです。

takeContentChanged のチェックも重要なステップのようです。

メソッドを次のように記述した場合:

protected void onStartLoading() {
    forceLoad();
}

onStartLoading子アクティビティが表示されてから親アクティビティに戻ると、 (などloadInBackground) が再度呼び出されることに気付くでしょう。

あなたは何ができますか?コンストラクター内で内部変数 ( mContentChanged) を true に設定します。次に、この変数を 内でチェックしますonStartLoading。true の場合のみ、実際に読み込みを開始します。

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();
        }
    }
}
于 2013-10-20T18:10:23.707 に答える
1

https://code.google.com/p/android/issues/detail?id=14944での議論を見ると、チェックtakeContentChangedも重要なステップのようです。

protected void onStartLoading() {
    if (mCursor != null) {
        deliverResult(mCursor);
    }
    if (takeContentChanged() || mCursor == null) {
        forceLoad();
    }
}
于 2013-03-19T07:26:21.090 に答える
0

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 を返します。

于 2016-08-17T10:31:06.467 に答える
-2

データのロードが呼び出されないという問題がまだありました。最終的にAsyncTaskLoader (サポート ライブラリ バージョン) を削除し、(サポート ライブラリからではなく) AsyncTaskのみを使用して作業を行いました。そしてそれはうまくいきました。

あなたのニーズにも十分かもしれません。

説明と例: http://developer.android.com/reference/android/os/AsyncTask.html

クラスAsyncTaskを拡張する必要があります。

メソッドdoInBackgroundが作業を行い、メソッドonPostExecuteで結果を取得します。AsyncTaskを開始するには、そのインスタンスでメソッドexecuteを呼び出します。リンクを参照してください。

于 2013-07-01T06:10:00.857 に答える