[Translate] Use fragment to process configuration changes (handling configuration changes with fragments)

Source: Internet
Author: User

Original address

This kind of problem is common on stackoverflow.

What's the best retain active Objects-such as runningthreads,sockets, andasynctasks-across device Configuration Ch Anges?

Before answering the question, let's talk about the difficulties developers typically encounter in dealing with the time-consuming tasks associated with the activity lifecycle.

Next, we'll discuss the drawbacks of two common methods.

Finally, we will use the persistence framgnet as the instance code to give a recommended solution.

Screen Rotation & background tasks

The problem with screen rotation is that activity has to undergo a life-cycle refactoring, and events are unpredictable. The processing of background concurrency tasks is no more than an aggravating problem.

For example, after the activity started Asynctask, the user rotated the phone screen, causing the activity to be destroyed and rebuilt. When Asynctask completes the task, it mistakenly gives the result to the old activity without knowing that the activity is being created. Because the new activity does not know the existence of asynctask and the final result, it will restart the asynctask, resulting in a waste of resources. Therefore, in the process of screen rotation, it is very important to save activity information correctly and effectively.

Bad method: The direction of fixed activity

The most trickery and abused method in the world is to prevent the reconfiguration of activity by fixing the activity direction.

Set in the Androidmanifest.xml fileandroid:configChanges

This simple approach is very appealing to developers. Google engineers do not recommend this approach.

The first step is to use code to handle screen rotation, meaning that it takes more effort to ensure that each string (string), layout, size (dimen) is kept in sync with the current screen orientation, and that improper handling can easily result in a series of resource-specific bugs.

Another reason Google discourages the use of this approach is that many developers mistakenly set android:configChanges="orientation" (for example) accidentally protecting the underlying activity from destruction and refactoring. Not only screen rotation, but also a variety of reasons for configuration changes, the device to the monitor, change the default language, change the default font size is only three trigger events that will change the configuration. Therefore, setting android:configChanges is not a good method.

Obsolete, rewriting onRetainNonConfigurationInstance()

Before the Android Honeycomb (Android 3.1 system, translator note) version, it is recommended to rewrite onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() transfer objects between multiple activity instances. onRetainNonConfigurationInstance()used to pass an object and getLastNonConfigurationInstance() used to get an object. In the API (Android 3.2 system, translator Note) These methods are obsolete and support the use of a more convenient modular approach setRetainInstance(boolean) to saving objects in fragment. We will discuss this approach in the next section.

Recommended: Managing objects in persistent fragment

Starting with Android 3.0, the concept of fragment is introduced, and the way to persist objects in activity is to wrap and manage these objects by persisting fragment. By default, the refactoring of fragment is followed by the refactoring of the parent activity when the configuration changes. By calling Fragment#setRetainInstance(true) , the process of destroying the rebuild is skipped, telling the system to maintain the state of the current fragment instance when the Acitivity is rebuilt. This runs on us, and the Thread AsyncTask use of Socket persistent fragment becomes quite advantageous.

The following sample code demonstrates how to use persistent fragment to save Asynctask in the case of configuration changes. The code guarantees a progress update and correctly passes the results to the activity, without revealing the Asynctask reference when the configuration changes.
The code consists of two classes, the first of which is mainactivity

 * This Activity displays the screens ' s UI, creates a taskfragment * to manage the task, and receives progress updates and Results * from the taskfragment when they occur. */public class Mainactivity extends Activity implements Taskfragment.taskcallbacks {private static final String Tag_task  _fragment = "Task_fragment";  Private Taskfragment mtaskfragment;    @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);    Setcontentview (R.layout.main);    Fragmentmanager fm = Getfragmentmanager ();    Mtaskfragment = (taskfragment) fm.findfragmentbytag (tag_task_fragment);    If the Fragment is non-null and then it's currently being//retained across a configuration change.      if (mtaskfragment = = null) {mtaskfragment = new taskfragment ();    Fm.begintransaction (). Add (Mtaskfragment, tag_task_fragment). commit ();  }//Todo:initialize views, restore saved state, etc. }//The four methods below is called by the taskfragment when New//Progress updates or results is available.  The mainactivity//should respond by updating it UI to indicate the change.  @Override public void OnPreExecute () {...}  @Override public void onprogressupdate (int percent) {...}  @Override public void oncancelled () {...} @Override public void OnPostExecute () {...}}

and Taskfragment

 * This Fragment manages a single background task and retains * itself across configuration changes. */public class Taskfragment extends Fragment {/** * Callback interface through which the Fragment would report the *   Task ' s progress and results back to the Activity.    */interface Taskcallbacks {void OnPreExecute ();    void onprogressupdate (int percent);    void oncancelled ();  void OnPostExecute ();  } private Taskcallbacks Mcallbacks;  Private Dummytask Mtask; /** * Hold a reference to the parent Activity so we can report the * task's current progress and results.   The Android framework * would pass us a reference to the newly created Activity after * each configuration change.    */@Override public void Onattach (activity activity) {Super.onattach (activity);  Mcallbacks = (taskcallbacks) activity;   }/** * This method would have only been called once when the retained * Fragment is first created. */@Override public void onCreate (Bundle savedinstancestATE) {super.oncreate (savedinstancestate);    Retain This fragment across configuration changes.    Setretaininstance (TRUE);    Create and execute the background task.    Mtask = new Dummytask ();  Mtask.execute ();   }/** * Set the callback to null so we don ' t accidentally leak the Activity instance.    */@Override public void Ondetach () {Super.ondetach ();  Mcallbacks = null;  }/** * A dummy task, performs some (dumb) background work and * proxies progress updates and results back to the   Activity. * * Note that we need to check if the callbacks is null in each * method in case they is invoked after the Activity '   S and * Fragment ' s OnDestroy () method has been called.       */Private class Dummytask extends Asynctask<void, Integer, void> {@Override protected Void OnPreExecute () {      if (mcallbacks! = null) {Mcallbacks.onpreexecute (); }}/** * Note that we don't call the callback object ' s methods * directly from the background thread, as this could result * in a race condition. */@Override protected void doinbackground (void ... ignore) {for (int i = 0;!iscancelled () && i < 1 00;        i++) {systemclock.sleep (100);      Publishprogress (i);    } return null; } @Override protected void Onprogressupdate (Integer ... percent) {if (mcallbacks! = null) {MCALLBACKS.O      Nprogressupdate (Percent[0]);      }} @Override protected void oncancelled () {if (mcallbacks! = null) {mcallbacks.oncancelled (); }} @Override protected void onpostexecute (void ignore) {if (mcallbacks! = null) {Mcallbacks.onpo      Stexecute (); }    }  }}
Event Flow

When MainActivity first started, the instantiation is added to the activity at the same time TaskFragment . TaskFragmentCreate and execute AsyncTask to pass the update results back to the MainActivity pass TaskCallbacks -through interface.

When the configuration changes, the MainActivity normal life cycle method, once the new activity is created, will callback the Fragmentd onAttach(Activity) method, even if the configuration changes, to ensure that fragment is currently holding a reference to the latest activity.

The results of the code run are simple and reliable, and the application framework processes the instances after the activity is rebuilt, TaskFragment and AsyncTask does not need to focus on configuration changes. onPostExecute()can be onDetach() onAttach() executed between the and method callbacks.
Refer to the answers on StackOverflow and the questions on Google + to answer Doug Stevenson.

Conclusion

The processing of synchronization background tasks related to the activity lifecycle is tricky, and configuration changes can be confusing. Fortunately, the persistence of fragment makes the handling of these events simple, even in the case of refactoring, by long-term holding of references to parent activity.
You can download the code on the Play store, source on GitHub, downloads, import to eclipse, change it at will;)

Summary of Translator's note screen rotation
    • When you do not set the activity's android:configchanges, the screen will recall the various lifecycles, and will be executed once when the screen is cut, and twice when the vertical screen is cut.
    • When you set the activity's android:configchanges= "orientation", the screen will recall the life cycle, and it will only execute once when you cut the horizontal and vertical screen.
    • When you set the activity's android:configchanges= "Orientation|keyboardhidden", the screen does not recall the individual lifecycles, only the Onconfigurationchanged method is executed
Change of opinion
    • Welcome to the point where the translation is wrong

[Translate] Use fragment to process configuration changes (handling configuration changes with fragments)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.