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

Reply via email to