Your issue sounds like it could be different than mine since I'm generally seeing onLoadFinished() called in initLoader(). You might want to do more web or StackOverflow searching or search the Android bug database -- I think somewhere I read about a problem where onLoadFinished() would not be called, but I think it only happens if you don't do the stuff that CursorLoader does. In other words, to solve your issue, you might have to copy a bunch of code from CursorLoader.
As to my issue, I never reported it since there didn't seem to be any interest in it. I just worked around it in my app. Thanks. On Mon, Jul 2, 2012 at 5:17 AM, szakalinhoPL <szakali...@gmail.com> wrote: > Hi, I noticed same situation, I'm not an expert but it seems like a bug > because behaviour of onLoadFinished is not normal according to > documentation which says that onLoadFinished should be called in > initLoader, but it never does. In very simple application it happens as > well. Did you report it or find out an answer? > > > On Wednesday, April 11, 2012 11:05:41 PM UTC+1, Malcolm Evershed wrote: >> >> *[My apologies if this is posted twice, it has been a few days and my >> original post didn't show up yet, so I'm attempting to post again]* >> >> >> I think I've found an issue where LoaderManager.LoaderCallbacks<**D>.* >> onLoadFinished*() will be called unnecessarily twice when rotating the >> device. *Is this expected behavior or should I open a bug?* >> >> >> >> This can easily be reproduced by running *ApiDemos *-> *App *-> *Loader *-> >> *Cursor *(which corresponds to the *LoaderCursor.java* example) and >> rotating the device. >> >> >> >> 1) Here's the first location where onLoadFinished() is called: >> >> >> >> LoaderCursor$**CursorLoaderListFragment.**onLoadFinished(Loader, Cursor) >> line: 159 >> >> LoaderCursor$**CursorLoaderListFragment.**onLoadFinished(Loader, Object) >> line: 1 >> >> LoaderManagerImpl$LoaderInfo.**callOnLoadFinished(Loader, Object) line: >> 438 >> >> *LoaderManagerImpl$LoaderInfo.reportStart() line: 318 * >> >> LoaderManagerImpl.**doReportStart() line: 778 >> >> LoaderCursor$**CursorLoaderListFragment(**Fragment).performStart() line: >> 1534 >> >> FragmentManagerImpl.**moveToState(Fragment, int, int, int) line: >> 862 >> >> FragmentManagerImpl.**moveToState(int, int, int, boolean) line: >> 1032 >> >> FragmentManagerImpl.**moveToState(int, boolean) line: 1014 >> >> FragmentManagerImpl.**dispatchStart() line: 1771 >> >> *LoaderCursor(Activity).performStart()* line: 4481 >> >> ActivityThread.**performLaunchActivity(**ActivityThread$**ActivityClientRecord, >> Intent) line: 1929 >> >> ActivityThread.**handleLaunchActivity(**ActivityThread$**ActivityClientRecord, >> Intent) line: 1981 >> >> ActivityThread.**handleRelaunchActivity(**ActivityThread$**ActivityClientRecord) >> line: 3351 >> >> ActivityThread.access$700(**ActivityThread, >> ActivityThread$**ActivityClientRecord) >> line: 123 >> >> ActivityThread$H.**handleMessage(Message) line: 1151 >> >> ActivityThread$H(Handler).**dispatchMessage(Message) line: 99 >> >> Looper.loop() line: 137 >> >> ActivityThread.main(String[]) line: 4424 >> >> Method.invokeNative(Object, Object[], Class, Class[], Class, int, >> boolean) line: not available [native method] >> >> Method.invoke(Object, Object...) line: 511 >> >> ZygoteInit$**MethodAndArgsCaller.run() line: 784 >> >> ZygoteInit.main(String[]) line: 551 >> >> NativeStart.main(String[]) line: not available [native method] >> >> >> >> Basically, as the Activity is starting up, *Activity.performStart*() >> calls mFragments.dispatchStart() which eventually calls >> Fragment.performStart(), which then calls mLoaderManager.doReportStart()* >> *. Ultimately, *LoaderManagerImpl$LoaderInfo.reportStart*() checks if >> the loader has been started and whether *mReportNextStart *is set (it >> was set when Fragment.performDestroyView() was called on the old fragment) >> and then it'll call onLoadFinished(). >> >> >> >> 2) Here's the second location where onLoadFinished() is called during the >> same rotation: >> >> >> >> LoaderCursor$**CursorLoaderListFragment.**onLoadFinished(Loader, Cursor) >> line: 159 >> >> LoaderCursor$**CursorLoaderListFragment.**onLoadFinished(Loader, Object) >> line: 1 >> >> LoaderManagerImpl$LoaderInfo.**callOnLoadFinished(Loader, Object) line: >> 438 >> >> *LoaderManagerImpl$LoaderInfo.finishRetain() line: 309 * >> >> LoaderManagerImpl.**finishRetain() line: 765 >> >> *LoaderCursor(Activity).performStart() line: 4485 * >> >> ActivityThread.**performLaunchActivity(**ActivityThread$**ActivityClientRecord, >> Intent) line: 1929 >> >> ActivityThread.**handleLaunchActivity(**ActivityThread$**ActivityClientRecord, >> Intent) line: 1981 >> >> ActivityThread.**handleRelaunchActivity(**ActivityThread$**ActivityClientRecord) >> line: 3351 >> >> ActivityThread.access$700(**ActivityThread, >> ActivityThread$**ActivityClientRecord) >> line: 123 >> >> ActivityThread$H.**handleMessage(Message) line: 1151 >> >> ActivityThread$H(Handler).**dispatchMessage(Message) line: 99 >> >> Looper.loop() line: 137 >> >> ActivityThread.main(String[]) line: 4424 >> >> Method.invokeNative(Object, Object[], Class, Class[], Class, int, >> boolean) line: not available [native method] >> >> Method.invoke(Object, Object...) line: 511 >> >> ZygoteInit$**MethodAndArgsCaller.run() line: 784 >> >> ZygoteInit.main(String[]) line: 551 >> >> NativeStart.main(String[]) line: not available [native method] >> >> >> >> Basically, *Activity.performStart*() calls LoaderManagerImpl.**finishRetain() >> (shortly after calling mFragments.dispatchStart() in the first callstack >> above). Ultimately, *LoaderManagerImpl$LoaderInfo.finishRetain*() checks >> if the loader has been started and whether *mReportNextStart *is cleared >> (it was just cleared by LoaderManagerImpl$LoaderInfo.**reportStart() in >> the first callstack above) and then it'll call onLoadFinished(). >> >> >> >> >> >> Here is my guess of what is really going on during a rotation: >> >> - Activity.performStart() ultimately causes this sequence of calls: >> - LoaderManagerImpl$LoaderInfo.*reportStart*() (from >> mFragments.dispatchStart()) >> - LoaderManagerImpl$LoaderInfo.*finishRetain*() (from >> LoaderManagerImpl.**finishRetain()) >> - LoaderManagerImpl$LoaderInfo.*reportStart*() (from >> LoaderManagerImpl.**doReportStart()) >> - LoaderManagerImpl$LoaderInfo.*reportStart*() and >> LoaderManagerImpl$LoaderInfo.*finishRetain*() use the *mReportNextStart >> *flag to determine whether to call onLoadFinished(), but this flag >> usage isn't designed for the sequence of calls above. It seems like maybe >> 2 >> flags may be required to cover all the possibilities of call sequences. >> >> >> >> But that's just my guess, I'm new to this code. :) >> >> >> Thanks. >> > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en > -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en