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

Reply via email to