Home | History | Annotate | Download | only in resources
      1 page.title=Tratar alteraes no tempo de execuo
      2 page.tags=atividade,ciclo de vida
      3 @jd:body
      4 
      5 <div id="qv-wrapper">
      6 <div id="qv">
      7 
      8   <h2>Neste documento</h2>
      9   <ol>
     10     <li><a href="#RetainingAnObject">Reteno de um objeto durante uma alterao de configurao</a></li>
     11     <li><a href="#HandlingTheChange">Tratar voc mesmo da alterao de configurao</a>
     12   </ol>
     13 
     14   <h2>Veja tambm</h2>
     15   <ol>
     16     <li><a href="providing-resources.html">Fornecimento de recursos</a></li>
     17     <li><a href="accessing-resources.html">Acesso aos recursos</a></li>
     18     <li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Alterao
     19 mais rpida da orientao da tela</a></li>
     20   </ol>
     21 </div>
     22 </div>
     23 
     24 <p>Algumas configuraes do dispositivo podem mudar durante o tempo de execuo
     25 (como orientao de tela, disponibilidade do teclado e idioma). Quando ocorre uma alterao,
     26 o Android precisa reiniciar a execuo
     27 de {@link android.app.Activity} ({@link android.app.Activity#onDestroy()}  chamado, seguido de {@link
     28 android.app.Activity#onCreate(Bundle) onCreate()}). O comportamento de reincio foi projetado para ajudar
     29 o aplicativo a se adaptar a novas configuraes recarregando automaticamente o aplicativo
     30 com recursos alternativos que correspondam com a configurao do dispositivo.</p>
     31 
     32 <p>Para tratar adequadamente um reincio,  importante que a atividade se restaure
     33 ao estado anterior por meio do <a href="{@docRoot}guide/components/activities.html#Lifecycle">ciclo de vida
     34 da atividade</a>, no qual o Android chama
     35 {@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} antes de destruir
     36 a atividade para que seja possvel salvar os dados acerca do estado do aplicativo. Em seguida,  possvel restaurar o estado
     37 durante {@link android.app.Activity#onCreate(Bundle) onCreate()} ou {@link
     38 android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p>
     39 
     40 <p>Para testar se o aplicativo se reinicia com o estado de aplicativo intacto, deve-se
     41 invocar as alteraes de configurao (como alteraes na orientao da tela) enquanto executa diversas
     42 tarefas no aplicativo. O aplicativo deve ser capaz de reiniciar a qualquer momento sem perda
     43 de dados do usurio ou estado para tratar eventos como alteraes de configurao ou quando o usurio recebe
     44 uma chamada telefnica e, em seguida, retorna ao aplicativo bem depois
     45 de destrudo o processo do aplicativo. Para ver como restaurar o estado da atividade, leia sobre o <a href="{@docRoot}guide/components/activities.html#Lifecycle">Ciclo de vida da atividade</a>.</p>
     46 
     47 <p>No entanto, pode-se encontrar uma situao em que o reincio do aplicativo
     48 e a restaurao representem quantidades significativas de dados que podem ser custosos e prejudicar a experincia do usurio. Nessa situao,
     49 temos duas opes:</p>
     50 
     51 <ol type="a">
     52   <li><a href="#RetainingAnObject">Reter um objeto durante uma alterao de configurao</a>
     53   <p>Permita que a atividade reinicie quando uma configurao muda, mas transporte um objeto
     54 de estado para a nova instncia da atividade.</p>
     55 
     56   </li>
     57   <li><a href="#HandlingTheChange">Tratar voc mesmo da alterao de configurao</a>
     58   <p>Evite que o sistema reinicie a atividade durante certas alteraes
     59 de configurao, mas receba um retorno de chamada quando as configuraes se alteram, para que voc atualize manualmente
     60 a atividade conforme necessrio.</p>
     61   </li>
     62 </ol>
     63 
     64 
     65 <h2 id="RetainingAnObject">Reteno de um objeto durante uma alterao de configurao</h2>
     66 
     67 <p>Se a reteno da atividade exigir a recuperao de grandes conjuntos de dados, restabelecer uma conexo
     68 de rede ou executar outras operaes intensivas, um reincio completo devido a uma alterao
     69 de configurao pode prejudicar a experincia do usurio. Alm disso, pode no ser possvel restaurar completamente
     70 o estado da atividade com o {@link android.os.Bundle} que o sistema salva com o retorno de chamada {@link
     71 android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} &mdash; ele
     72 no foi projetado para transportar objetos grandes (como bitmaps) e os dados contidos devem ser serializados
     73 e, em seguida, desserializados, o que pode consumir muita memria e retardar a alterao de configurao. Nesse caso,
     74 para aliviar o peso de reinicializar a atividade, pode-se reter um {@link
     75 android.app.Fragment} quando a atividade for reiniciada devido a uma alterao de configurao. Esse fragmento
     76 pode conter referncias a objetos com estado que seja preciso reter.</p>
     77 
     78 <p>Quando o sistema Android encerra a atividade devido a uma alterao de configurao, os fragmentos
     79 da atividade marcados para serem retidos no so destrudos.  possvel adicionar esses fragmentos
     80  atividade para preservar objetos de estado.</p>
     81 
     82 <p>Para reter objetos de estado em um fragmento durante uma alterao de configurao em tempo de execuo:</p>
     83 
     84 <ol>
     85   <li>Estenda a classe {@link android.app.Fragment} e declare referncias aos objetos
     86 de estado.</li>
     87   <li>Chame {@link android.app.Fragment#setRetainInstance(boolean)} quando o fragmento for criado.
     88       </li>
     89   <li>Acrescente o fragmento  atividade.</li>
     90   <li>Use {@link android.app.FragmentManager} para recuperar o fragmento quando a atividade for
     91 reiniciada.</li>
     92 </ol>
     93 
     94 <p>Por exemplo: defina o fragmento da seguinte forma:</p>
     95 
     96 <pre>
     97 public class RetainedFragment extends Fragment {
     98 
     99     // data object we want to retain
    100     private MyDataObject data;
    101 
    102     // this method is only called once for this fragment
    103     &#64;Override
    104     public void onCreate(Bundle savedInstanceState) {
    105         super.onCreate(savedInstanceState);
    106         // retain this fragment
    107         setRetainInstance(true);
    108     }
    109 
    110     public void setData(MyDataObject data) {
    111         this.data = data;
    112     }
    113 
    114     public MyDataObject getData() {
    115         return data;
    116     }
    117 }
    118 </pre>
    119 
    120 <p class="caution"><strong>Ateno:</strong> ao restaurar qualquer objeto,
    121 no se deve nunca passar um objeto vinculado a {@link android.app.Activity}, como um {@link
    122 android.graphics.drawable.Drawable}, um {@link android.widget.Adapter}, um {@link android.view.View}
    123 ou qualquer outro objeto associado a um {@link android.content.Context}. Se o fizer,
    124 ele vazar todas as vistas e recursos da instncia da atividade original (vazar recursos
    125 significa que o aplicativo mantm a reteno deles, que no podem ser recolhidos, o que
    126 causa perda de memria).</p>
    127 
    128 <p>Em seguida, use {@link android.app.FragmentManager} para adicionar o fragmento  atividade.
    129  possvel obter o objeto de dados do fragmento quando a atividade reiniciar durante as alteraes
    130 de configurao em tempo de execuo. Por exemplo: defina a atividade da seguinte forma:</p>
    131 
    132 <pre>
    133 public class MyActivity extends Activity {
    134 
    135     private RetainedFragment dataFragment;
    136 
    137     &#64;Override
    138     public void onCreate(Bundle savedInstanceState) {
    139         super.onCreate(savedInstanceState);
    140         setContentView(R.layout.main);
    141 
    142         // find the retained fragment on activity restarts
    143         FragmentManager fm = getFragmentManager();
    144         dataFragment = (DataFragment) fm.findFragmentByTag(data);
    145 
    146         // create the fragment and data the first time
    147         if (dataFragment == null) {
    148             // add the fragment
    149             dataFragment = new DataFragment();
    150             fm.beginTransaction().add(dataFragment, data).commit();
    151             // load the data from the web
    152             dataFragment.setData(loadMyData());
    153         }
    154 
    155         // the data is available in dataFragment.getData()
    156         ...
    157     }
    158 
    159     &#64;Override
    160     public void onDestroy() {
    161         super.onDestroy();
    162         // store the data in the fragment
    163         dataFragment.setData(collectMyLoadedData());
    164     }
    165 }
    166 </pre>
    167 
    168 <p>Nesse exemplo, {@link android.app.Activity#onCreate(Bundle) onCreate()} adiciona um fragmento
    169 ou restaura uma referncia a ele. {@link android.app.Activity#onCreate(Bundle) onCreate()} tambm
    170 armazena o objeto de estado dentro da instncia de fragmento.
    171 {@link android.app.Activity#onDestroy() onDestroy()} atualiza o objeto de estado dentro
    172 da instncia de fragmento retida.</p>
    173 
    174 
    175 
    176 
    177 
    178 <h2 id="HandlingTheChange">Tratar voc mesmo da alterao de configurao</h2>
    179 
    180 <p>Se o aplicativo no tiver que atualizar recursos durante uma alterao de configurao especfica
    181 <em>e</em> se houver alguma limitao de desempenho que
    182 impea a atividade de reiniciar, pode-se declarar que a atividade trata ela mesma da alterao de configurao,
    183 o que evita que o sistema reinicie a atividade.</p>
    184 
    185 <p class="note"><strong>Observao:</strong> Tratar voc mesmo da alterao de configurao
    186 pode dificultar muito o uso de recursos alternativos, pois o sistema no os aplicar
    187 automaticamente. Esta tcnica deve ser considerada um ltimo recurso, quando  preciso evitar reincios
    188 devido a uma alterao de configurao e no  recomendada para a maioria dos aplicativos.</p>
    189 
    190 <p>Para declarar que a atividade manipula uma alterao de configurao, edite o elemento <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
    191 apropriado no arquivo de manifesto para que inclua o atributo <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
    192 android:configChanges}</a> com um valor que represente a configurao
    193 a tratar. Os valores possveis esto listados na documentao do atributo <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
    194 android:configChanges}</a> (os valores mais comumente usados so {@code "orientation"}, para
    195 impedir reincios durante alteraes na orientao da tela, e {@code "keyboardHidden"} para impedir
    196 reincios quando a disponibilidade do teclado muda).  Para declarar vrios valores de configurao
    197 no atributo, usa-se um separador na forma de caractere barra reta {@code |}.</p>
    198 
    199 <p>Por exemplo: o cdigo de manifesto a seguir declara uma atividade que trata tanto
    200 da alterao de orientao da tela quanto da disponibilidade do teclado:</p>
    201 
    202 <pre>
    203 &lt;activity android:name=".MyActivity"
    204           android:configChanges="orientation|keyboardHidden"
    205           android:label="@string/app_name">
    206 </pre>
    207 
    208 <p>Agora, quando uma dessas configuraes mudar, {@code MyActivity} no reiniciar.
    209 Em vez disso, a {@code MyActivity} recebe uma chamada para {@link
    210 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Um objeto
    211 {@link android.content.res.Configuration}  passado a esse mtodo e especifica
    212 a nova configurao do dispositivo. Ao ler os campos em {@link android.content.res.Configuration},
    213 pode-se determinar a nova configurao e atualizar os recursos na interface para fazer
    214 as alteraes adequadas. No momento
    215 em que o mtodo  chamado, o objeto {@link android.content.res.Resources} da atividade  atualizado
    216 para retornar recursos com base na nova configurao, o que facilita
    217 a redefinio de elementos da IU sem que o sistema reinicie a atividade.</p>
    218 
    219 <p class="caution"><strong>Ateno:</strong> a partir do Android 3.2 (nvel da API 13), <strong>o "tamanho
    220 da tela" tambm muda</strong> quando o dispositivo alterna entre as orientaes retrato
    221 e paisagem. Assim, se voc deseja evitar que o tempo de execuo reinicie devido a uma mudana da orientao
    222 ao desenvolver uma API nvel 13 ou posterior (conforme declarado pelos atributos <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> e <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>),
    223  preciso incluir o valor {@code "screenSize"} alm do valor {@code
    224 "orientation"}. Ou seja,  preciso declarar {@code
    225 android:configChanges="orientation|screenSize"}. No entanto, se o aplicativo tem como alvo uma API nvel
    226 12 ou inferior, a atividade sempre trata ela mesma a alterao de configurao (essa mudana
    227 de configurao no reinicia a atividade, mesmo em execuo em Android 3.2 ou dispositivo posterior).</p>
    228 
    229 <p>Por exemplo: a implementao a seguir {@link
    230 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} verifica
    231 a orientao de dispositivo atual:</p>
    232 
    233 <pre>
    234 &#64;Override
    235 public void onConfigurationChanged(Configuration newConfig) {
    236     super.onConfigurationChanged(newConfig);
    237 
    238     // Checks the orientation of the screen
    239     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
    240         Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    241     } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
    242         Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    243     }
    244 }
    245 </pre>
    246 
    247 <p>O objeto {@link android.content.res.Configuration} representa todas as configuraes
    248 atuais, no somente as que foram alteradas. Na maior parte do tempo, no importa como
    249 a configurao foi alterada; basta reatribuir todos os recursos que apresentam alternativas
    250  configurao que esto sendo tratadas. Por exemplo: como o objeto {@link
    251 android.content.res.Resources} est atualizado, pode-se redefinir
    252 qualquer {@link android.widget.ImageView} com {@link android.widget.ImageView#setImageResource(int)
    253 setImageResource()}
    254 e ser usado o recurso adequado  nova configurao (conforme descrito em <a href="providing-resources.html#AlternateResources">Como fornecer recursos</a>).</p>
    255 
    256 <p>Observe que os valores dos campos de {@link
    257 android.content.res.Configuration} so inteiros que correspondem a constantes especficas
    258 da classe {@link android.content.res.Configuration}. Para ver a documentao sobre as constantes
    259 a usar em cada campo, consulte o campo em questo na referncia sobre {@link
    260 android.content.res.Configuration}.</p>
    261 
    262 <p class="note"><strong>Lembre-se:</strong> ao declarar a atividade para tratar uma alterao
    263 de configurao, voc  responsvel por redefinir todos os elementos que fornecem alternativas. Se voc
    264 declarar a atividade para tratar a alterao de orientao e tiver imagens que alterariam
    265 entre paisagem e retrato,  preciso reatribuir cada recurso a cada elemento durante {@link
    266 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
    267 
    268 <p>Se no for necessrio atualizar o aplicativo com base nessas alteraes
    269 de configurao, pode-se <em>no</em> implementar {@link
    270 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Nesse
    271 caso, todos os recursos usados antes da alterao de configurao ainda so usados
    272 e somente o reincio da atividade  evitado. No entanto, o aplicativo deve sempre ser capaz
    273 de se encerrar e reiniciar com seu estado anterior intacto, portanto essa tcnica no deve
    274 ser considerada uma fuga da reteno do estado durante o ciclo de vida normal da atividade, No somente porque
    275 h outras alteraes de configurao impossveis de evitar que reiniciem o aplicativo,
    276 mas tambm porque devem-se tratar eventos como o do usurio que sai do aplicativo e ele  destrudo
    277 antes de o usurio voltar a ele.</p>
    278 
    279 <p>Para obter mais informaes sobre as alteraes de configurao que devem ser tratadas na atividade, consulte a documentao sobre <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
    280 android:configChanges}</a> e a classe
    281 {@link android.content.res.Configuration}.</p>
    282