国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android屏幕旋轉(zhuǎn) 處理Activity與AsyncTask的最佳解決方案

2019-12-12 04:13:37
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一、概述

運(yùn)行時(shí)變更就是設(shè)備在運(yùn)行時(shí)發(fā)生變化(例如屏幕旋轉(zhuǎn)、鍵盤(pán)可用性及語(yǔ)言)。發(fā)生這些變化,Android會(huì)重啟Activity,這時(shí)就需要保存activity的狀態(tài)及與activity相關(guān)的任務(wù),以便恢復(fù)activity的狀態(tài)。

為此,google提供了三種解決方案:

  • 對(duì)于少量數(shù)據(jù): 通過(guò)onSaveInstanceState(),保存有關(guān)應(yīng)用狀態(tài)的數(shù)據(jù)。 然后在 onCreate()onRestoreInstanceState() 期間恢復(fù) Activity 狀態(tài)。
  • 對(duì)于大量數(shù)據(jù):用 Fragment 保留需要回復(fù)的對(duì)象。
  • 自行處理配置變更,不重啟Activity。

下面會(huì)逐一介紹三種情況,其實(shí)保存一些變量對(duì)象很簡(jiǎn)單,難的是當(dāng)Activity創(chuàng)建異步線程去加載數(shù)據(jù)時(shí),旋轉(zhuǎn)屏幕時(shí),怎么保存線程的狀態(tài)。比如,在線程的加載過(guò)程中,旋轉(zhuǎn)屏幕,就會(huì)存在問(wèn)題:此時(shí)數(shù)據(jù)沒(méi)有完成加載,onCreate重新啟動(dòng)時(shí),會(huì)再次啟動(dòng)線程;而上個(gè)線程可能還在運(yùn)行,并且可能會(huì)更新已經(jīng)不存在的控件,造成錯(cuò)誤。下面會(huì)一一解決這些問(wèn)題。本文較長(zhǎng),主要是代碼多,可以先下載demo,源碼下載:http://download.csdn.net/detail/jycboy/9720486對(duì)比著看。

 二、使用onSaveInstanceState,onRestoreInstanceState​

代碼如下:

/** * 使用onSaveInstanceState,onRestoreInstanceState; * 在這里不考慮沒(méi)有加載完畢,就旋轉(zhuǎn)屏幕的情況。 * @author 超超boy * */public class SavedInstanceStateActivity extends ListActivity{ private static final String TAG = "MainActivity"; private ListAdapter mAdapter; private ArrayList<String> mDatas; private DialogFragment mLoadingDialog; private LoadDataAsyncTask mLoadDataAsyncTask; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e(TAG, "onCreate"); initData(savedInstanceState); } /** * 初始化數(shù)據(jù) */ private void initData(Bundle savedInstanceState) { if (savedInstanceState != null) mDatas = savedInstanceState.getStringArrayList("mDatas"); if (mDatas == null) { mLoadingDialog = new LoadingDialog(); mLoadingDialog.show(getFragmentManager(), "LoadingDialog"); mLoadDataAsyncTask = new LoadDataAsyncTask(); mLoadDataAsyncTask.execute(); //mLoadDataAsyncTas } else { initAdapter(); } } /** * 初始化適配器 */ private void initAdapter() { mAdapter = new ArrayAdapter<String>( SavedInstanceStateActivity.this, android.R.layout.simple_list_item_1, mDatas); setListAdapter(mAdapter); } @Override protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); Log.e(TAG, "onRestoreInstanceState"); } @Override //在這里保存數(shù)據(jù),好用于返回 protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.e(TAG, "onSaveInstanceState"); outState.putSerializable("mDatas", mDatas); } /** * 模擬耗時(shí)操作 * * @return */ private ArrayList<String> generateTimeConsumingDatas() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return new ArrayList<String>(Arrays.asList("通過(guò)Fragment保存大量數(shù)據(jù)", "onSaveInstanceState保存數(shù)據(jù)", "getLastNonConfigurationInstance已經(jīng)被棄用", "RabbitMQ", "Hadoop", "Spark")); } private class LoadDataAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { mDatas = generateTimeConsumingDatas(); return null; } @Override protected void onPostExecute(Void result) { mLoadingDialog.dismiss(); initAdapter(); } } @Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); }}

界面為一個(gè)ListView,onCreate中啟動(dòng)一個(gè)異步任務(wù)去加載數(shù)據(jù),這里使用Thread.sleep模擬了一個(gè)耗時(shí)操作;當(dāng)用戶(hù)旋轉(zhuǎn)屏幕發(fā)生重新啟動(dòng)時(shí),會(huì)onSaveInstanceState中進(jìn)行數(shù)據(jù)的存儲(chǔ),在onCreate中對(duì)數(shù)據(jù)進(jìn)行恢復(fù),免去了不必要的再加載一遍。

運(yùn)行結(jié)果:

12-24 20:13:41.814 1994-1994/? E/MainActivity: onCreate
12-24 20:13:46.124 1994-1994/? E/MainActivity: onSaveInstanceState
12-24 20:13:46.124 1994-1994/? E/MainActivity: onDestroy
12-24 20:13:46.154 1994-1994/? E/MainActivity: onCreate
12-24 20:13:46.164 1994-1994/? E/MainActivity: onRestoreInstanceState

當(dāng)正常加載數(shù)據(jù)完成之后,用戶(hù)不斷進(jìn)行旋轉(zhuǎn)屏幕,log會(huì)不斷打出:onSaveInstanceState->onDestroy->onCreate->onRestoreInstanceState,驗(yàn)證Activity重新啟動(dòng),但是我們沒(méi)有再次去進(jìn)行數(shù)據(jù)加載。

如果在加載的時(shí)候,進(jìn)行旋轉(zhuǎn),則會(huì)發(fā)生錯(cuò)誤,異常退出(退出原因:dialog.dismiss()時(shí)發(fā)生NullPointException,因?yàn)榕c當(dāng)前對(duì)話框綁定的FragmentManager為null,在這里這個(gè)不是關(guān)鍵)。

效果圖:

三、使用Fragment保留對(duì)象,恢復(fù)數(shù)據(jù)

果重啟 Activity 需要恢復(fù)大量數(shù)據(jù)、重新建立網(wǎng)絡(luò)連接或執(zhí)行其他密集操作,依靠系統(tǒng)通過(guò)onSaveInstanceState() 回調(diào)為您保存的 Bundle,可能無(wú)法完全恢復(fù) Activity 狀態(tài),因?yàn)樗⒎窃O(shè)計(jì)用于攜帶大型對(duì)象(例如位圖),而且其中的數(shù)據(jù)必須先序列化,再進(jìn)行反序列化,這可能會(huì)消耗大量?jī)?nèi)存并使得配置變更速度緩慢。 在這種情況下,如果 Activity 因配置變更而重啟,則可通過(guò)保留 Fragment 來(lái)減輕重新初始化 Activity 的負(fù)擔(dān)。此片段可能包含對(duì)您要保留的有狀態(tài)對(duì)象的引用。

當(dāng) Android 系統(tǒng)因配置變更而關(guān)閉 Activity 時(shí),不會(huì)銷(xiāo)毀您已標(biāo)記為要保留的 Activity 的片段。 您可以將此類(lèi)片段添加到 Activity 以保留有狀態(tài)的對(duì)象。

要在運(yùn)行時(shí)配置變更期間將有狀態(tài)的對(duì)象保留在片段中,請(qǐng)執(zhí)行以下操作:

  • 擴(kuò)展 Fragment 類(lèi)并聲明對(duì)有狀態(tài)對(duì)象的引用。
  • 在創(chuàng)建片段后調(diào)用 setRetainInstance(boolean)。
  • 將片段添加到 Activity。
  • 重啟 Activity 后,使用 FragmentManager 檢索片段。

例如,按如下方式定義片段:

public class RetainedFragment extends Fragment { // data object we want to retain private MyDataObject data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(MyDataObject data) { this.data = data; } public MyDataObject getData() { return data; }}

注意:盡管您可以存儲(chǔ)任何對(duì)象,但是切勿傳遞與 Activity 綁定的對(duì)象,例如,Drawable、Adapter、View 或其他任何與 Context 關(guān)聯(lián)的對(duì)象。否則,它將使Activity無(wú)法被回收造成內(nèi)存泄漏。(泄漏資源意味著應(yīng)用將繼續(xù)持有這些資源,但是無(wú)法對(duì)其進(jìn)行垃圾回收,因此可能會(huì)丟失大量?jī)?nèi)存)

下面舉一個(gè)實(shí)際的例子:

1.RetainedFragment

public class RetainedFragment extends Fragment{ // data object we want to retain private Bitmap data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(Bitmap data) { this.data = data; } public Bitmap getData() { return data; }}

只是保持Bitmap對(duì)象的引用,你可以用Fragment保存多個(gè)對(duì)象。

2.FragmentRetainDataActivity:

public class FragmentRetainDataActivity extends Activity{ private static final String TAG = "FragmentRetainData"; private RetainedFragment dataFragment; private DialogFragment mLoadingDialog; private ImageView mImageView; private Bitmap mBitmap; BitmapWorkerTask bitmapWorkerTask; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG, "onCreate"); // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); dataFragment = (RetainedFragment) fm.findFragmentByTag("data"); // create the fragment and data the first time if (dataFragment == null) { // add the fragment dataFragment = new RetainedFragment(); fm.beginTransaction().add(dataFragment, "data").commit(); } // the data is available in dataFragment.getData() mBitmap = dataFragment.getData(); initView(); } /** * 初始化控件 */ private void initView() { mImageView = (ImageView) findViewById(R.id.id_imageView); if(mBitmap != null) mImageView.setImageBitmap(mBitmap); //圖片為空時(shí),加載圖片;有時(shí)候即使dataFragment!=null時(shí),圖片也不一定就加載完了,比如在加載的過(guò)程中,旋轉(zhuǎn)屏幕,此時(shí)圖片就沒(méi)有加載完 else{ mLoadingDialog = new LoadingDialog(); mLoadingDialog.show(getFragmentManager(), "LOADING_DIALOG"); bitmapWorkerTask = new BitmapWorkerTask(this); bitmapWorkerTask.execute("http://images2015.cnblogs.com/blog/747969/201612/747969-20161222164357995-1098775233.jpg"); } } /** * 異步下載圖片的任務(wù)。 * 設(shè)置成靜態(tài)內(nèi)部類(lèi)是為了防止內(nèi)存泄漏 * @author guolin */ private static class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { //圖片的URL地址 private String imageUrl; //保存外部activity的弱引用 private WeakReference<Context> weakReference; public BitmapWorkerTask(Context context) { weakReference = new WeakReference<>(context); } @Override protected Bitmap doInBackground(String... params) { imageUrl = params[0]; //為了演示加載過(guò)程,阻塞2秒 try {Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return downloadUrlToStream(imageUrl); } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); if(bitmap !=null){ FragmentRetainDataActivity retainDataActivity= (FragmentRetainDataActivity) weakReference.get(); //調(diào)用回調(diào)方法 retainDataActivity.onLoaded(bitmap); } } /** * 建立HTTP請(qǐng)求,并獲取Bitmap對(duì)象。 * 修改了下 * @param urlString * 圖片的URL地址 * @return 解析后的Bitmap對(duì)象 */ private Bitmap downloadUrlToStream(String urlString) { HttpURLConnection urlConnection = null; Bitmap bitmap = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){ //連接成功  InputStream is = urlConnection.getInputStream();  bitmap = BitmapFactory.decodeStream(is);  is.close();  return bitmap; }else{  return null; } } catch (final IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) {  urlConnection.disconnect(); } } return null; } } //加載完畢的回掉 public void onLoaded(Bitmap bitmap){ mBitmap = bitmap; mLoadingDialog.dismiss(); mImageView.setImageBitmap(mBitmap); // load the data from the web dataFragment.setData(mBitmap); Log.e(TAG, "onLoaded"); } public void onPause(){ super.onPause(); Log.e(TAG, "onPause"); if(getFragmentManager() != null && mLoadingDialog != null) mLoadingDialog.dismiss(); } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "onDestroy"); if(bitmapWorkerTask !=null) bitmapWorkerTask.cancel(true); // store the data in the fragment dataFragment.setData(mBitmap); }}

這里邊用BitmapWorkerTask異步下載圖片,downloadUrlToStream封裝了下載圖片的代碼;

BitmapWorkerTask用弱引用保持外部Activity對(duì)象防止內(nèi)存泄漏,下載完畢后用onLoaded回調(diào)方法更新UI。

通過(guò)檢查dataFragment、mBitmap判斷是否已經(jīng)加載過(guò),加載過(guò)直接用就可以。

效果圖:

在gif里可以看到,如果未加載完畢就旋轉(zhuǎn)屏幕,它會(huì)重新啟動(dòng)異步線程去下載,這種效果并不好,我們會(huì)在最后解決這個(gè)問(wèn)題。

四、自行處理配置變更

如果應(yīng)用在特定配置變更期間無(wú)需更新資源,并且因性能限制您需要盡量避免重啟,則可聲明 Activity 將自行處理配置變更,這樣可以阻止系統(tǒng)重啟 Activity。

要聲明由 Activity 處理配置變更,需設(shè)置清單文件manifest:

<activity android:name=".MyActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/app_name">

"orientation" 和 "keyboardHidden",分別用于避免因屏幕方向和可用鍵盤(pán)改變而導(dǎo)致重啟)。您可以在該屬性中聲明多個(gè)配置值,方法是用管道 | 字符分隔這些配置值。

注意:API 級(jí)別 13 或更高版本的應(yīng)用時(shí),若要避免由于設(shè)備方向改變而導(dǎo)致運(yùn)行時(shí)重啟,則除了 "orientation" 值以外,您還必須添加 "screenSize" 值。 也就是說(shuō),您必須聲明 android:configChanges="orientation|screenSize"。

當(dāng)其中一個(gè)配置發(fā)生變化時(shí),MyActivity 不會(huì)重啟。相反,MyActivity 會(huì)收到對(duì)onConfigurationChanged() 的調(diào)用。向此方法傳遞Configuration 對(duì)象指定新設(shè)備配置。您可以通過(guò)讀取Configuration 中的字段,確定新配置,然后通過(guò)更新界面中使用的資源進(jìn)行適當(dāng)?shù)母摹?/p>

例如,以下onConfigurationChanged() 實(shí)現(xiàn)檢查當(dāng)前設(shè)備方向:

@Overridepublic void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig);  // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); }}

示例代碼:

public class ConfigChangesTestActivity extends ListActivity{ private static final String TAG = "MainActivity"; private ListAdapter mAdapter; private ArrayList<String> mDatas; private DialogFragment mLoadingDialog; private LoadDataAsyncTask mLoadDataAsyncTask; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e(TAG, "onCreate"); initData(savedInstanceState); } /** * 初始化數(shù)據(jù) */ private void initData(Bundle savedInstanceState) { mLoadingDialog = new LoadingDialog(); mLoadingDialog.show(getFragmentManager(), "LoadingDialog"); mLoadDataAsyncTask = new LoadDataAsyncTask(); mLoadDataAsyncTask.execute(); } /** * 初始化適配器 */ private void initAdapter() { mAdapter = new ArrayAdapter<String>(ConfigChangesTestActivity.this, android.R.layout.simple_list_item_1, mDatas); setListAdapter(mAdapter); } /** * 模擬耗時(shí)操作 * * @return */ private ArrayList<String> generateTimeConsumingDatas() { try { Thread.sleep(2000); } catch (InterruptedException e) { } return new ArrayList<String>(Arrays.asList("通過(guò)Fragment保存大量數(shù)據(jù)", "onSaveInstanceState保存數(shù)據(jù)", "getLastNonConfigurationInstance已經(jīng)被棄用", "RabbitMQ", "Hadoop", "Spark")); } /** * 當(dāng)配置發(fā)生變化時(shí),不會(huì)重新啟動(dòng)Activity。但是會(huì)回調(diào)此方法,用戶(hù)自行進(jìn)行對(duì)屏幕旋轉(zhuǎn)后進(jìn)行處理 */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } } private class LoadDataAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { mDatas = generateTimeConsumingDatas(); return null; } @Override protected void onPostExecute(Void result) { mLoadingDialog.dismiss(); initAdapter(); } } @Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); }}

這種方法使用簡(jiǎn)單,在回調(diào)方法onConfigurationChanged執(zhí)行你的操作就可以,不會(huì)重啟Activity。

但是自行處理配置變可能導(dǎo)致備用資源的使用更為困難,因此不到萬(wàn)不得已不用,大部分情況推薦用Fragment。

效果圖:

五、旋轉(zhuǎn)屏幕時(shí)如果任務(wù)線程未執(zhí)行完,如何保存恢復(fù)

解決上邊提到的問(wèn)題,在未加載完畢的情況下,旋轉(zhuǎn)屏幕,保存任務(wù)線程,重啟activity不重新執(zhí)行異步線程。那么他的難點(diǎn)就是保存任務(wù)線程,不銷(xiāo)毀它,用上邊三個(gè)方法都可以實(shí)現(xiàn),推薦用1,2種方法。下邊就主要介紹用第二種方法Fragment,那么你也肯定想到了,用Fragment保存AsyncTask就可以了。

代碼如下:

1. OtherRetainedFragment

/** * 保存對(duì)象的Fragment * @author 超超boy * */public class OtherRetainedFragment extends Fragment{ // data object we want to retain // 保存一個(gè)異步的任務(wù) private MyAsyncTask data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(MyAsyncTask data) { this.data = data; } public MyAsyncTask getData() { return data; }

和之前差不多就是保存對(duì)象是MyAsyncTask。

2.MyAsyncTask:

public class MyAsyncTask extends AsyncTask<Void, Void, Void>{ //保存外部activity的弱引用 private WeakReference<Context> weakReference; public MyAsyncTask(Context context) { weakReference = new WeakReference<>(context); } private FixProblemsActivity activity; /** * 是否完成 */ private boolean isCompleted; /** * 進(jìn)度框 */ private LoadingDialog mLoadingDialog; private List<String> items; /** * 開(kāi)始時(shí),顯示加載框 */ @Override protected void onPreExecute() { mLoadingDialog = new LoadingDialog(); activity = (FixProblemsActivity) weakReference.get(); if(activity != null) mLoadingDialog.show(activity.getFragmentManager(), "LOADING"); } /** * 加載數(shù)據(jù) */ @Override protected Void doInBackground(Void... params) { items = loadingData(); return null; } /** * 加載完成回調(diào)當(dāng)前的Activity */ @Override protected void onPostExecute(Void unused) { isCompleted = true; notifyActivityTaskCompleted(); if (mLoadingDialog != null) mLoadingDialog.dismiss(); } public List<String> getItems() { return items; } private List<String> loadingData() { try { Thread.sleep(5000); } catch (InterruptedException e) { } return new ArrayList<String>(Arrays.asList("通過(guò)Fragment保存大量數(shù)據(jù)", "onSaveInstanceState保存數(shù)據(jù)", "getLastNonConfigurationInstance已經(jīng)被棄用", "RabbitMQ", "Hadoop", "Spark")); } /** * 設(shè)置Activity,因?yàn)锳ctivity會(huì)一直變化 * * @param activity */ public void setActivity(Context activity) { weakReference = new WeakReference<>(activity); // 設(shè)置為當(dāng)前的Activity this.activity = (FixProblemsActivity) activity; // 開(kāi)啟一個(gè)與當(dāng)前Activity綁定的等待框 if (activity != null && !isCompleted) { mLoadingDialog = new LoadingDialog(); mLoadingDialog.show(this.activity.getFragmentManager(), "LOADING"); } // 如果完成,通知Activity if (isCompleted) { notifyActivityTaskCompleted(); } } /** * 在Activity不可見(jiàn)時(shí),關(guān)閉dialog */ public void dialogDismiss(){ if(mLoadingDialog != null){ mLoadingDialog.dismiss(); } } private void notifyActivityTaskCompleted() { if (null != activity) { activity.onTaskCompleted(); } }}
  • 和之前一樣保留Activity的虛引用,防止內(nèi)存泄漏。
  • setActivity()方法用于任務(wù)未完成時(shí),重啟activity相應(yīng)的創(chuàng)建一個(gè)新的dialog。
  • dialogDismiss用于在在Activity不可見(jiàn)時(shí),關(guān)閉dialog,防止以前的dialog造成內(nèi)存泄漏。
  • 當(dāng)任務(wù)完成時(shí),調(diào)用activity的回調(diào)方法onTaskCompleted更新UI。

3.FixProblemsActivity

public class FixProblemsActivity extends ListActivity{ private static final String TAG = "MainActivity"; private ListAdapter mAdapter; private List<String> mDatas; private OtherRetainedFragment dataFragment; private MyAsyncTask mMyTask; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e(TAG, "onCreate"); // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); dataFragment = (OtherRetainedFragment) fm.findFragmentByTag("data"); // create the fragment and data the first time if (dataFragment == null) { // add the fragment dataFragment = new OtherRetainedFragment(); fm.beginTransaction().add(dataFragment, "data").commit(); } mMyTask = dataFragment.getData(); if (mMyTask != null) { //與新的Activity進(jìn)行綁定 mMyTask.setActivity(this); } else { //啟動(dòng)一個(gè)新的 mMyTask = new MyAsyncTask(this); dataFragment.setData(mMyTask); mMyTask.execute(); } // the data is available in dataFragment.getData() } @Override protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); Log.e(TAG, "onRestoreInstanceState"); } @Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); } @Override //在這里關(guān)閉Dialog,否則容易造成內(nèi)存泄漏 protected void onPause() { super.onPause(); mMyTask.dialogDismiss(); } /** * 回調(diào)方法,更新UI * 這里如果在加載的過(guò)程中按下返回鍵返回主Activity時(shí),會(huì)出現(xiàn)異常,setAdapter on a null object reference。因?yàn)閍ctivity被銷(xiāo)毀, * 要解決這個(gè)問(wèn)題,可以監(jiān)聽(tīng)返回鍵事件做相應(yīng)處理。 */ public void onTaskCompleted() { mDatas = mMyTask.getItems(); mAdapter = new ArrayAdapter<String>(FixProblemsActivity.this, android.R.layout.simple_list_item_1, mDatas); setListAdapter(mAdapter); }}

主要在onCreate方法中執(zhí)行一些邏輯判斷,如果沒(méi)有開(kāi)啟任務(wù)(第一次進(jìn)入),開(kāi)啟任務(wù);如果已經(jīng)開(kāi)啟了,調(diào)用setActivity(this);

在onPause中關(guān)閉dialog,防止內(nèi)存泄漏。

設(shè)置了等待5秒,足夠旋轉(zhuǎn)三四個(gè)來(lái)回了~~~~可以看到雖然在不斷的重啟,但是絲毫不影響任務(wù)的運(yùn)行和加載框的顯示~~~~

效果圖:

寫(xiě)著寫(xiě)著就這么晚了,本以為會(huì)寫(xiě)的很快。。中間Androidstudio的錄制視頻的功能還不好使啦,逼得我在手機(jī)上下了個(gè)。。。好分析到此結(jié)束。

查閱資料時(shí)的一些參考文檔:

https://developer.android.google.cn/guide/topics/resources/runtime-changes.html#HandlingTheChange

http://blog.csdn.net/lmj623565791/article/details/37936275

https://developer.android.google.cn/guide/components/activities.html

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持武林網(wǎng)!

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 奉新县| 娱乐| 通州区| 民和| 张家界市| 三原县| 和平区| 海盐县| 桐柏县| 博兴县| 三河市| 嘉黎县| 汝州市| 游戏| 鄄城县| 石屏县| 常宁市| 疏勒县| 三原县| 平昌县| 宜兰市| 崇文区| 阿拉善盟| 武城县| 监利县| 丹凤县| 闽侯县| 吉水县| 阿拉善左旗| 剑阁县| 许昌县| 宣威市| 黔西县| 于都县| 米脂县| 滦南县| 太和县| 休宁县| 门头沟区| 蒲城县| 晋江市|