It might be because onQueryTextChange is being called on orientation changes... so restartLoader is called each time, thus resulting in two calls to onLoadFinished. I haven't tested this, but I suspect it is the problem here. I forgot my USB cable at work but I'll try to remember to test it out. I doubt it is a bug though... it seems like the last LoaderManager bug should have been squashed a long time ago, given that it has been over a year since HoneyComb's release.
Alex On Monday, July 2, 2012 4:49:50 PM UTC-4, Malcolm Evershed wrote: > > 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 <[email protected]> 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 [email protected] >> To unsubscribe from this group, send email to >> [email protected] >> 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 [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

