пакет совместимости для Android - фрагмент ... не прикреплен к Activity - PullRequest
22 голосов
/ 29 июля 2011

Здравствуйте, Я сталкиваюсь с этой проблемой: Я использую пакет совместимости для использования фрагмента в приложении для Android (минимум SDK 2.1).

Иногда на фрагменте возникает случайное исключение, и я не могу понять, почему. Это трассировка стека, которую я получаю:

java.lang.IllegalStateException: Fragment FeedListFragment{438a54e8} not attached to Activity
    at android.support.v4.app.Fragment.getLoaderManager(Fragment.java:715)
    at com.myappli.ui.FeedListFragment.refreshUpdateDate(FeedListFragment.java:283)
    at com.myappli.ui.phone.FeedListActivity.onReceiveResult(FeedListActivity.java:277)
    at com.myappli.data.rssplayer.service.KTDetachableResultReceiver.onReceiveResult(KTDetachableResultReceiver.java:55)
    at android.os.ResultReceiver$MyRunnable.run(ResultReceiver.java:43)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:4425)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)

Вот соответствующий код, который я вызываю в классе Fragment:

public class FeedListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>, FeedListCursorAdapterListener {

...
    public void refreshUpdateDate() {
    getLoaderManager().restartLoader(LAST_UPDATE_CURSOR_ID, null, this);
    }
...
}

Вот код действия, которое вызывает фрагмент:

private FeedListFragment mCursorLoaderListFg;

if (!isFinishing()) {
    mCursorLoaderListFg.refreshUpdateDate();
    mCursorLoaderListFg.refreshDisplay();
    mCursorLoaderListFg.hideLoadingArticles();
}

Вот фрагмент исходного кода для getLoaderManager ():

/**
* Return the LoaderManager for this fragment, creating it if needed.
*/
public LoaderManager getLoaderManager() {
    if (mLoaderManager != null) {
        return mLoaderManager;
    }
    if (mActivity == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }
    mCheckedForLoaderManager = true;
    mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
    return mLoaderManager;
}

Вот шаги приложения до сбоя:

  1. Операция вызывает методы в фоновом режиме.
  2. Методы обратного вызова вызываются для действия
  3. В этом методе обратного вызова действие вызывает фрагмент
  4. Фрагмент пытается запустить некоторые методы (например, getLoadManager ()), которые требуют активности.
  5. Фрагмент больше не привязан к активности => крах

Мы попробовали два исправления:

  • тест на активность, чтобы проверить, заканчивается ли активность (как в коде выше)
  • тест на фрагмент с методом isDetached.

Спасибо за вашу помощь !!!

Не стесняйтесь спрашивать меня больше информации, если мне не ясно.

Ответы [ 4 ]

27 голосов
/ 23 августа 2011

У меня была похожая проблема.

Попробуйте использовать isAdded() или isVisible() вместо isDetached().К сожалению, isDetached() не работает должным образом ...

1 голос
/ 11 декабря 2012

Что мне помогло, так это использование прослушивателя фрагмента фрагмента, добавление для него функции getActivity, которая возвращает активность прослушивателя фрагмента (действия, создавшего фрагмент).

Теперь, когда у меня есть вызов, который требует активности, я просто использую функцию.

0 голосов
/ 21 декабря 2012

Фрагмент будет прикреплен к активности по событию Fragment.onAttach (Activity).Ваша активность должна реализовывать слушателя, обеспечивает фрагмент.Чтобы гарантировать, что ваш метод refreshUpdateDate () будет вызываться только после события, onAttach () должен сначала принять действие как реализацию слушателя, а затем вызвать метод фрагмента listenAttached ().Таким образом, ваша активность будет проинформирована, когда фрагмент прикреплен, и функция refreshUpdateDate () может быть вызвана, например, напрямую в fragAttached ().См. Создание обратных вызовов событий для действия .

0 голосов
/ 12 марта 2012

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

private static class MessagesAdapter extends CursorAdapter {
...

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

...