Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Neither of the two methods here works. Both are prone to a problem when the calling Activity is replaced by the system (for instance, via screen rotation).</p> <p>In Commonsware's answer, the OnContactPickedListener assigned by requestContact() will refer to a control that no longer exists.</p> <p>In my own answer, the listener retained by the Activity will vanish, and the new activity's equivalent listener will be null.</p> <p>However there is a solution, which relies on making the context of the listener reassignable.</p> <p>Drawing on my previous solution, recast the ActivityResultListener interface as a static class:</p> <pre><code>abstract public static class ActivityResultListener { private Context context_; public ActivityResultListener( Context context ) { context_ = context; } public Context getContext() { return context_; } public void setContext( Context context ) { context_ = context; } abstract public void onResultCode( int resultCode, Intent data ); } </code></pre> <p>Set up an internal class to record state for the BaseActivity:</p> <pre><code>protected static class BaseState { private final ActivityResultListener activity_result_listener_; protected BaseState( BaseActivity activity ) { activity_result_listener_ = activity.activity_result_listener_; } protected void setState( BaseActivity activity ) { activity.activity_result_listener_ = activity_result_listener_; if (activity.activity_result_listener_ != null) { activity.activity_result_listener_.setContext( activity ); } } } </code></pre> <p>Note especially the call to setContext() in setState(). This avoids the problems associated with non-static interface implementations, i.e. that their references vanish when the Activity is recreated.</p> <p>Retain state from within the BaseActivity:</p> <pre><code>@Override public Object onRetainNonConfigurationInstance() { return new BaseState( this ); } </code></pre> <p>Restore state from within BaseActivity.onCreate()</p> <pre><code>Object state = getLastNonConfigurationInstance(); if (state instanceof BaseState) { ((BaseState)state).setState( this ); } </code></pre> <p>In the implementation of ActivityResultListener, be sure to use getContext() and findViewById() to dereference everything on demand rather than storing references:</p> <pre><code>private static class ContactChoiceListener extends BaseActivity.ActivityResultListener { private final int id_; public ContactChoiceListener( Context context, int id ) { super( context ); id_ = id; } @Override public void onResultCode( int resultCode, Intent data ) { if (resultCode == BaseActivity.RESULT_OK) { AddressEditor editor = (AddressEditor)((BaseActivity)getContext()).findViewById( id_ ); if (editor != null) editor.add_contact_address( data ); } } } </code></pre> <p>Whew. And the best part is, this is all obsolete because Fragments have a completely different way of dealing with state, using setRetainInstance(boolean).</p> <p>I will be implementing that version shortly, will post here if there is interest.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload