02.03.2011 16:23, Thierry Legras пишет:
(putting again CC to android as your answer seems quite usefull to android community!)

Thank you. I meant to reply to the list, but Thunderbird sometimes has other ideas :) And good luck to you with resolving the issue.


Wow, thanks Kostya, I am impressed by this so detailed answer :). Answers inline.


2011/3/2 Kostya Vasilyev <[email protected] <mailto:[email protected]>>

    Yes, if the activity isn't getting recreated, there won't be
    onRestoreInstanceState due to activity lifecycle. However it can
    still be called on the spinner view under certain conditions.

    For a cursor-based adapter, a managed cursor gets closed/reopened
    when the activity is paused / resumed, which causes the data set
    to be invalidated.

    AdapterView saves and restores selection state when that happens,
    by calling onSaveInstanceState / onRestoreInstanceState on itself:
    see AdapterDataSetObserver in AdapterView.java.

    Selection state *can* be delivered asynchronously, when an adapter
    view is undergoing a layout: see SelectionNotifier in the same
    source file. That's another possibility, that the spinner is
    undergoing a layout, and actually, AdapterView does request layout
    when the data set changes - so we're back to the question of, what
    kind of adapter are you using for the spinner?


Indeed, my spinner use a SimpleCursorAdapter. It seems in my case, the view is underoing a layout after selected tab has been changed and the new view containing the spinner needs to be drawn.


    A couple practical things to try that came to my mind are:

    1 - Post selection change from Activity B to tab1 asynchronously,
    using a Handler, after calling setCurrentTab;


If this works, this would be a neat solution as it will clearly keep separated activites code.
I will definitively try that instead of my dirty flag trick, thanks :-)


    2 - If tab activities have onResume called when switched (I
    haven't used tabs, so don't know) ...


Not in my case as tab 1 content is not an activity but only a view. so when I select tab 2, Activity A (which is the TabActivity) does not pause, but stay actives.

    ... - you could set the new selection state as a member variable
    in tab1, and set the new selection in its onResume (probably after
    calling the base class).

    Finally, as a side note, this falls into the 0,01% of bugs for
    which it's very useful to have Android framework sources installed
    in the Eclipse debugger. I have detailed instructions in my blog,
    under tools - it recently really helped me resolve a similar bug
    caused by interference with that very same code in AdapterView.


Thanks again for this tip!
BTW your blog looks like a goldmine to me, I think I will re-use your IP address EditText :)

Thierry.



    -- Kostya

    02.03.2011 14:21, Thierry Legras пишет:
    Hi Kostya,

    Thanks to try to help to sort this out. unfortunatly I don't
    think this is the cause in this case:

    Activity A is a TabActivity that embeds activity B being in tab
    2. Indeed when I select tab 1 from activity B using
    setCurrentTabByTag , _Activity A is already in running state_ (I
    checked onResume was called earlier), so I dont think
    onRestoreInstanceState will be called here.

    Also I tried to place a breakpoint in onItemSelected, but this
    was no help, it seems to be triggered using runOnUIThread() or
    similar.

    But on the idea, you are probably close. It seems Android is
    trying to restore an old state (spinner position). Either this is
    a bug, or I did not correctly used setSelection. I am wondering
    if calling setPosition from another activity is a safe pratice??

    Thierry.


    2011/3/2 Kostya Vasilyev <[email protected]
    <mailto:[email protected]>>

        Thierry,

        I think you are seeing interaction between the activity's
        onRestoreInstanceState and your setSelection.

        Should be pretty easy to check by overriding
        onRestoreInstanceState in ActivityA and/or the spinner and
        logging them - as well as your code that calls setSelection.
        Then you can re-run both scenarios from your original email
        and watch the exact sequence of events.

        -- Kostya

        02.03.2011 12:52, Thierry Legras пишет:

        Okay, as I could not find a way to fix that smoothly, I just
        used a flag ignoreNextOnItemSelected like described
        hereafter. Seems to me a dirty hack :(

        // called from another activity context
        updateSpinnerSelection(int newposition) {

            mPosition = newposition; // store it
            mSpinner.setSelection(newposition);
            ignoreNextOnItemSelected= true;
        }

        and

        public void onItemSelected(AdapterView<?> arg0, View arg1,
        int position,
                        long rowid) {
            if (ignoreNextOnItemSelected) {
                // position might be outdate ?!?! just reapply mPosition
                ignoreNextOnItemSelected = false;

                // required
                mSpinner.setSelection(mPosition);
            } else {
                mPosition = position;
                ... // do usual stuff
            }
        }



        2011/2/25 Thierry Legras <[email protected]
        <mailto:[email protected]>>

            Hi,

            I have a strange behavior in a very specific case and
            wonder if the issue comes from my code or not.

            I have a TabActivity A with 2 tabs:
            - Tab 1 content is created as a view with a spinner in it
            - Tab 2 content is an activity B.

            I want at some point when Tab2 is selected to switch to
            Tab 1 and update spinner selection in it.

            Case 1)
            Tab 2 is selected, from Activity B context:

            activityA.updateSpinnerSelection(newposition);
            activityA.getTabHost().setCurrentTabByTag(tab1tag);

            later AdapterView.OnItemSelectedListener.onItemSelected
            is called with my newposition

            => so this /usually /works fine:

            Case 2)
            Tab 2 is selected, from Activity B context, but before
            doing the same things, if the users for some reason
            *first open a new acticity C on top of B (like
            preference screen) and close this activity C*, (so A and
            B are paused then resumed), then if I later try again
            the same things:

            activityA.updateSpinnerSelection(newposition);
            activityA.getTabHost().setCurrentTabByTag(tab1tag);

            so far so goog, but later
            AdapterView.OnItemSelectedListener.onItemSelected is
            called not with newposition as argument *but with the
            older position value*.


            I hope the description is clear.

            Did I missed something? or could this behavior dues to
            some bug in Android?

            Thanks for any help,
-- Thierry.




-- Thierry. -- 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]
        <mailto:[email protected]>
        To unsubscribe from this group, send email to
        [email protected]
        <mailto:[email protected]>
        For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en


-- Kostya Vasilyev --http://kmansoft.wordpress.com

-- 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]
        <mailto:[email protected]>
        To unsubscribe from this group, send email to
        [email protected]
        <mailto:android-developers%[email protected]>
        For more options, visit this group at
        http://groups.google.com/group/android-developers?hl=en




-- Thierry.


-- Kostya Vasilyev --http://kmansoft.wordpress.com




--
Thierry.


--
Kostya Vasilyev -- http://kmansoft.wordpress.com

--
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