首页 > 代码库 > 3.App Resources-Handling Runtime Changes

3.App Resources-Handling Runtime Changes

Reference : http://blog.csdn.net/aliaooooo/article/details/23606179

 

1. Handling Runtime Changes

  Some device configurations can change during runtime (such as screen orientation, keyboard availability, and language). When such a

    change occurs, Android restarts the running Activity(onDestroy() is called, followed by onCreate()). The restart behavior is designed to

    help your application adapt to new configurations by automatically reloading your application with alternative resources that match the

    new device configuration.

  To properly handle a restart, it is important that your activity restores its previous state through the normal Activity lifecycle, in which

    Android calls onSaveInstanceState() before it destroys your activity so that you can save data about the application state. You can then

    restore the state during onCreate() or onRestoreInstanceState().

  However, you might encounter a situation in which restarting your application and restoring significant amounts of data can be costly and

    create a poor user experience. In such a situation, you have two other options:

  <1>Retaining an Object During a Configuration Change

  <2>Handle the configuration change yourself

 

2. Retaining an Object During a Configuration Change

  If restarting your activity requires that you recover large sets of data, re-establish a network connection, or perform other intensive

    operations, then a full restart due to a configuration change might be a slow user experience.

  Also, it might not be possible for you to completely restore your activity state with the Bundle that the system saves for you with the

    onSaveInstanceState() callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then

    deserialized, which can consume a lot of memory and make the configuration change slow.

  In such a situation, you can alleviate the burden of reinitializing your activity by retaining a Fragment when your activity is restarted due to a   

    configuration change. This fragment can contain references to stateful objects that you want to retain.

  When the Android system shuts down your activity due to a configuration change, the fragments of your activity that you have marked to

    retain are not destroyed. You can add such fragments to your activity to preserve stateful objects.

 

  To retain stateful objects in a fragment during a runtime configuration change:

  <1> Extend the Fragment class and declare refrences to your stateful objects

  <2> Call setRetainInstance(boolean) when the fragment is created

  <3> Add the fragment to your activity

  <4> Use FragmentManager to retrieve the fragment when the activity is restarted

//ConfigurationChangeHandlerTest.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="mirror.android.configurationchangehandlertest.ConfigurationChangeHandlerTest" >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="点击按钮启动线程模拟网络耗时操作,获取新闻详情显示在按钮下面" />        <Button        android:id="@+id/btn_createthread"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="获取娱乐新闻"/>        <TextView        android:id="@+id/tv_shownews"        android:layout_width="match_parent"          android:layout_height="match_parent"        android:textColor="@android:color/holo_green_dark"  /></LinearLayout>
//ConfigurationChangeHandlerTest.javapackage mirror.android.configurationchangehandlertest;import android.app.Activity;import android.app.ProgressDialog;import android.content.res.Configuration;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView;public class ConfigurationChangeHandlerTest extends Activity implements OnClickListener {    private final String TAG = "ConfiguartionTest";    private String newsInfo;        private Button button;    private TextView showNewsTextView;    private ProgressDialog progressDialog;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_configuration_change_handler_test);                button = (Button)findViewById(R.id.btn_createthread);        button.setOnClickListener(this);        showNewsTextView = (TextView)findViewById(R.id.tv_shownews);                if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){            Log.i( TAG ,"----onCreate - landscape---");        }        else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){            Log.i(TAG, "----onCreate - portrait ---");          }     }    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.btn_createthread:            excuteLongTimeOperation();            break;        }    }    private void excuteLongTimeOperation() {        progressDialog = ProgressDialog.show(ConfigurationChangeHandlerTest.this                                            , "Load Info"                                            , "Loading"                                            , true                                             , true);        Thread workerThread = new Thread(new MyNewThread());        workerThread.start();    }        class MyNewThread extends Thread{        @Override        public void run() {            try {                sleep(5000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            newsInfo = "10月20日,周杰伦御用作词人方文山在微博发声表示,周杰伦的第十三张专辑的所有歌曲已经录制完毕," +                    "此次专辑会收录超过十首歌曲,预计12月发行。网友纷纷表示期待“小十三等待实在太不易了”。" +                    "还有部分网友就之前蔡依林[微博]的新专辑《呸》调侃:杰伦新专辑名字是不是<<爱呸不呸>> ?";            Message message = handler.obtainMessage();            Bundle bundle = new Bundle();            bundle.putString("message", newsInfo);            message.setData(bundle);            handler.sendMessage(message);        }    }        private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            progressDialog.dismiss();            showNewsTextView.setText(newsInfo);        }    };    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        Log.i(TAG, "----onConfigurationChanged---");      }    @Override    protected void onStart() {        super.onStart();        Log.i(TAG, "----onStart---");    }    @Override    protected void onRestart() {        super.onRestart();        Log.i(TAG, "----onRestart---");    }    @Override    protected void onResume() {        super.onResume();        Log.i(TAG, "----onResume---");    }    @Override    protected void onPause() {        super.onPause();        Log.i(TAG, "----onPause---");    }    @Override    protected void onStop() {        super.onStop();        Log.i(TAG, "----onStop---");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.i(TAG, "----onDestroy---");    }        @Override    protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        Log.i(TAG, "----onSaveInstanceState---");     }}

  Run this appliction, then after sleep 5 seconds, show the news about "周杰伦". Then, change the Phone to landspace

     

  LogCat to observe

  

  This way works, but we change the screen orientation not until the sleep time ends, we will see

  

  

  

  

3.App Resources-Handling Runtime Changes