Dlaczego onLoadFinished jest wywoływany ponownie po wznowieniu fragmentu?

Mam dziwny problem z ładowarkami. Obecnie nie jestem pewien, czy jest to błąd w moim kodzie lub źle rozumiem ładowarki.

Aplikacja

Problem pojawia się w rozmowach (wyobraź sobie coś podobnego do Whatsapp). Używane przeze mnie ładowarki są implementowane w oparciu oPrzykład AsyncTaskLoader. Korzystam z biblioteki wsparcia.

W OnCreate uruchamiam program ładujący, aby pobrać buforowane wiadomości.Po zakończeniu CachedMessageLoader uruchamia RefreshLoader, aby pobrać (online) najnowsze wiadomości.Każdy typ programu ładującego jako odrębny identyfikator (powiedzmy offline: 1 online: 2)

Działa to bardzo dobrze, z następującym wyjątkiem.

Problem

Kiedy otwieram kolejny fragment (i dodaję transakcję do backstacka), a następnie używam Back-Key, aby wrócić do konwersacji,onLoadFinished jest wywoływany ponownie za pomocąobie wyniki z wcześniej. To wywołanie ma miejsce, zanim fragment ma szansę ponownie uruchomić program ładujący ...

To dostarczanie „starych” wyników, które otrzymałem wcześniej, skutkuje powieleniem wiadomości.

Pytanie

Dlaczego te wyniki są ponownie dostarczane?Czy używam tych ładowarek źle?Czy mogę „unieważnić” wyniki, aby upewnić się, że dostanę je tylko raz, czy też sam muszę wyeliminować duplikaty?

Ślad stosu połączeń

MyFragment.onLoadFinished(Loader, Result) line: 369 
MyFragment.onLoadFinished(Loader, Object) line: 1   
LoaderManagerImpl$LoaderInfo.callOnLoadFinished(Loader, Object) line: 427   
LoaderManagerImpl$LoaderInfo.reportStart() line: 307    
LoaderManagerImpl.doReportStart() line: 768 
MyFragment(Fragment).performStart() line: 1511  
FragmentManagerImpl.moveToState(Fragment, int, int, int, boolean) line: 957 
FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1104  
BackStackRecord.popFromBackStack(boolean) line: 764 
...

Aktualizacja 1 Wspomniane tutaj ładowarki są inicjowane przez fragment rozmowy:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    Bundle args = getArguments();
    m_profileId = args.getString(ArgumentConstants.ARG_USERID);
    m_adapter = new MessageAdapter(this);

    if (savedInstanceState != null) {
        restoreInstanceState(savedInstanceState);
    }
    if (m_adapter.isEmpty()) {
        Bundle bundle = new Bundle();
        bundle.putString(ArgumentConstants.ARG_USERID, m_profileId);
        getLoaderManager().restartLoader(R.id.loader_message_initial, bundle, this);
    } else {
        // Omitted: Some arguments passed in Bundle
        Bundle b = new Bundle(). 
        getLoaderManager().restartLoader(R.id.loader_message_refresh, b, this);
    }
}

@Override
public void onResume() {
    super.onResume();
    // Omitted: setting up UI state / initiating other loaders that work fine
}

@Override
public AbstractMessageLoader onCreateLoader(final int type, final Bundle bundle) {
    final SherlockFragmentActivity context = getSherlockActivity();
    context.setProgressBarIndeterminateVisibility(true);
    switch (type) {
        case R.id.loader_message_empty:
            return new EmptyOnlineLoader(context, bundle);
        case R.id.loader_message_initial:
            return new InitialDBMessageLoader(context, bundle);
        case R.id.loader_message_moreoldDB:
            return new OlderMessageDBLoader(context, bundle);
        case R.id.loader_message_moreoldOnline:
            return new OlderMessageOnlineLoader(context, bundle);
        case R.id.loader_message_send:
            sendPreActions();
            return new SendMessageLoader(context, bundle);
        case R.id.loader_message_refresh:
            return new RefreshMessageLoader(context, bundle);
        default:
            throw new UnsupportedOperationException("Unknown loader");
    }
}

@Override
public void onLoadFinished(Loader<Holder<MessageResult>> loader, Holder<MessageResult> holder) {
    if (getSherlockActivity() != null) {
        getSherlockActivity().setProgressBarIndeterminateVisibility(false);
    }
    // Omitted: Error handling of result (can contain exception)
    List<PrivateMessage> unreadMessages = res.getUnreadMessages();
    switch (type) {
        case R.id.loader_message_moreoldDB: {
            // Omitted error handling (no data)
            if (unreadMessages.isEmpty()) {
                m_hasNoMoreCached = true;
                // Launch an online loader
                Bundle b = new Bundle();
                // Arguments omitted
                getLoaderManager().restartLoader(R.id.loader_message_moreoldOnline, b, ConversationFragment.this);
            }
            // Omitted: Inserting results into adapter
        }
        case R.id.loader_message_empty: { // Online load when nothing in DB
            // Omitted: error/result handling handling
            break;
        }
        case R.id.loader_message_initial: { // Latest from DB, when opening
            // Omitted: Error/result handling

            // If we found nothing, request online
            if (unreadMessages.isEmpty()) {
                 Bundle b = new Bundle();
                 // Omitted: arguments
                 getLoaderManager().restartLoader(R.id.loader_message_empty, b, this);
             } else {
                // Just get new stuff
                Bundle b = new Bundle();
               // Omitted: Arguments
               getLoaderManager().restartLoader(R.id.loader_message_refresh, b, this);
            }
            break;
        }
        // Omitted: Loaders that do not start other loaders, but only add returned data to the adapter
        default:
            throw new IllegalArgumentException("Unknown loader type " + type);
    }
    // Omitted: Refreshing UI elements
}

@Override
public void onLoaderReset(Loader<Holder<MessageResult>> arg0) { }

Aktualizacja 2 Mój MainActivity (który ostatecznie hostuje wszystkie fragmenty) podklasuje SherlockFragmentActivity i zasadniczo uruchamia takie fragmenty:

    Fragment f = new ConversationFragment(); // Setup omitted
    f.setRetainInstance(false);
    // Omitted: Code related to navigation drawer
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.fragment_container_frame, f).commit();

Fragment rozmowy rozpoczyna fragment „profilu wyświetlania” w następujący sposób:

DisplayProfileFragment f = new DisplayProfileFragment();
// Arguments omitted
FragmentManager manager = getSherlockActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fragment_container_frame, f).addToBackStack(null).commit();

questionAnswers(1)

yourAnswerToTheQuestion