小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【Android】11.2 通過重寫對應的方法保存和恢復實例的狀態(tài)

 WindySky 2016-03-01

標簽:

分類:C#、Android、VS2015;

創(chuàng)建日期:2016-02-21

一、簡介

通過重寫(也叫回調)對應的方法來管理Activity的生命周期,比如用戶旋轉屏幕時應用程序要能自動保存和恢復實例的狀態(tài),這對于開發(fā)一個健壯而又靈活的應用程序而言至關重要。

1、本節(jié)要點

一旦真正理解了Activity的生命周期,就可以輕松自如地通過C#代碼去控制它了。這一節(jié)我們主要學習如何用Boundle存儲簡單類型的數(shù)據(jù)(比如int、double、string、bool、……等)。

當一個Activity停止或銷毀時,系統(tǒng)會存儲該Activity的狀態(tài),這個保存的狀態(tài)稱為實例狀態(tài)。在Activity的生命周期中,Android提供了存儲實例狀態(tài)的三個選項:

  • 在叫做Boundle的“key/value”字典中保存元數(shù)據(jù)的值。
  • 創(chuàng)建一個自定義的類,用該類來維持復雜數(shù)據(jù)的狀態(tài),比如圖像。
  • 不保存Activity的任何狀態(tài)。即:以上兩個事都不做。比如,從活動A轉到活動B后,活動A原來的臨時數(shù)據(jù)丟就丟了,反正活動B也用不到這些數(shù)據(jù)。

下面主要介紹前兩個選項。

2、利用Bundle保存和恢復場景(實例)的狀態(tài)

由于實例狀態(tài)保存在稱為Boundle的“key/value”字典中,因此,當創(chuàng)建一個Activty時,就可以在重寫的OnCreate()方法中傳遞boundle來恢復原來的實例狀態(tài)。

但是,不建議將圖像等復雜數(shù)據(jù)保存在boundle中,這是因為圖像不容易被串行化為“key/value”,這種情況下,應該將整個圖像文件作為一個簡單數(shù)據(jù)類型來看待(僅僅用字符串保存圖像的文件名或URL,而不是保存完整的圖像數(shù)據(jù))。

Bundle為Activity提供了“保存”和“恢復”實例狀態(tài)的兩個方法:

  • OnSaveInstanceState – 當開始銷毀Activity時Android將自動調用此方法。在這個方法中,可通過一系列【“鍵/值”對】來存儲需要保存的項。
  • OnRestoreInstanceState – 當OnCreate()方法完成后Android將自動調用此方法,通過重寫該方法,就可以恢復原來的狀態(tài)。

注:不要對“狀態(tài)”這個詞迷惑了,它的本質含義舉例來說就是:當活動A從可見變?yōu)椴豢梢?,然后再從不可見轉為可見后,活動A原來的數(shù)據(jù)、選項、……等“狀態(tài)”還需要在再次可見時重現(xiàn)嗎,如果需要重現(xiàn),就先在重寫的OnSaveInstanceState()方法中保存這些數(shù)據(jù)、選項、……等場景,然后再在重寫的OnRestoreInstanceState()方法中恢復這些場景。這樣一來,不管Android系統(tǒng)內部怎樣折騰,這些數(shù)據(jù)也不會丟了,仍然能在重新可見時重現(xiàn)原來的場景。

下圖演示了如何使用這兩個方法:

技術分享

(1)OnSaveInstanceState()方法

當一個Activity被Paused或者Stopped時,如果這個Activity對象仍然被保留在內存中,那么就可以簡單地通過Resume讓這個Activity返回到前臺。可是,當內存緊張時,系統(tǒng)可能會銷毀這個Activity,這樣程序就無法簡單地通過Resume還原這個Activity了。如果用戶還想返回到這個Activity,系統(tǒng)必須新建一個Activity讓用戶覺得原來的那個Activity還存在,可是如何還原到銷毀前的狀態(tài)呢?解決辦法就是讓系統(tǒng)在殺死那個Activity之前先調用OnSaveInstanceState()來保存原來的狀態(tài),這樣就可以用它去恢復了。

具體辦法是:在重寫的OnCreate()方法或者重寫的OnRestoreInstanceState()方法中從傳遞的Bundle中解析出保存的信息,并用它來恢復Activity原來的狀態(tài)。

如果原來并沒有儲存狀態(tài)信息,此時傳入的Bundle將為null,比如第1次創(chuàng)建Activity時就是這種情況。

總之,將Activity狀態(tài)完整地返回給用戶的兩種情況有:

(a)如果原來的Activity對象還保存在內存中,系統(tǒng)就直接通過Resumed還原原來的狀態(tài);

(b)如果原來的Activity對象已經不存在,系統(tǒng)就新建一個Activity,并檢查是否保存了原來的狀態(tài),如果保存了就還原它,否則將新建的狀態(tài)設置為null。

注意:系統(tǒng)不一定每次都在銷毀這個Activity之前調用OnSaveInstanceState()方法 ,比如用戶使用【Back】鍵關閉了這個Activity。在這種情況下,系統(tǒng)通常會在OnStop()方法之前或者在OnPause()之前調用OnSaveInstanceState(),而不是在銷毀前去調用它。

還有一些情況,比如在layout文件夾下的布局文件中聲明的控件,即使你不顯式調用OnSaveInstanceState()方法,系統(tǒng)仍然會默認將其狀態(tài)保存下來。但前提是你必須為想要保存其狀態(tài)的控件(widget)提供一個唯一的ID。如果不給widget指定ID,系統(tǒng)是無法保存它的狀態(tài)的。

另外,通過把android:saveEnabled 設置為"false",或者調用 SetSaveEnabled() 方法,也可以顯式地阻止layout中的某個view保存狀態(tài)。不過,通常不應該禁用保存,但是,假如你需要恢復activity UI的各個不同的狀態(tài),也許可以這么做。

盡管默認實現(xiàn)的 OnSaveInstanceState() 方法會保存activity UI的有用信息,但你仍然需要重寫(override)它來存入更多的信息。 例如,你可能需要保存在activity生命周期中改變的成員變量值(比如恢復UI的值,默認情況下,這些UI狀態(tài)的成員變量值是不會被恢復的)。

因為默認實現(xiàn)的 OnSaveInstanceState() 方法已經幫你保存了一些UI的狀態(tài),所以如果你為了保存更多的狀態(tài)信息而重寫此方法,那么在執(zhí)行自己的代碼之前應該確保先調用一次父類的 OnSaveInstanceState() 方法。同理,如果重寫 OnRestoreInstanceState(),也應該調用一次父類的該方法,這樣缺省的代碼就能正?;謴蛌iew的狀態(tài)了。

注意:因為 OnSaveInstanceState() 并不保證每次都會被調用,所以你應該只用它來記錄activity的一些臨時狀態(tài)信息(UI的狀態(tài))——千萬不要用它來保存那些需要長久保存的數(shù)據(jù)(比如那些需要存入數(shù)據(jù)庫里的數(shù)據(jù)),而是應該在用戶離開activity的時候在重寫的 OnPause()方法中來保存這些永久性數(shù)據(jù)。

一個檢測應用程序狀態(tài)恢復能力的好辦法就是旋轉設備,使屏幕方向發(fā)生改變(在模擬器中可通過按<Ctrl>+<F11>讓其旋轉)。當屏幕的方向改變時,因為要換用符合實際屏幕參數(shù)的資源,所以系統(tǒng)會銷毀并重建這個activity。正因如此,你的activity在被重建時能完整地恢復狀態(tài)非常重要,因為用戶可能會在使用應用程序時頻繁地旋轉屏幕。

本節(jié)的例子演示了如何在重寫的OnSaveInstanceState()方法中保存狀態(tài)數(shù)據(jù)。在這個例子中,用戶每單擊一次按鈕,都會將count的值加1,并在TextView中將count的值顯示出來。當改變配置狀態(tài)時--比如用戶旋轉屏幕時--會丟失count的值(此時boundle將會為null),重而寫該Activity的OnSaveInstanceState()方法即可保存count的值。這樣一來,當設備旋轉到一個新的狀態(tài)時(比如按<Ctrl>+<F11>將模擬器從縱向變?yōu)闄M向),由于count的值已經保存到boundle中,因此可通過下面的辦法重新獲取這個值:

count = bundle.GetInt ("counter", -1);

注意:調用base.OnSaveInstanceState (outState)非常重要,這能確保始終存儲視圖的層次結構的所有原始狀態(tài)。

(2)OnRestoreInstanceState()方法

設備的某些配置可能會在運行時發(fā)生變化(比如屏幕方向、鍵盤可用性以及國家語言等狀態(tài)發(fā)生了變化)。當發(fā)生這些變化時,Android會重建這個運行中的activity,即:系統(tǒng)會先調用OnDestroy() ,再調用OnCreate()。這種設計有助于應用程序適用新的參數(shù)配置,措施就是通過把你預置的可替換資源(比如對應各種屏幕方向和尺寸的layout)自動重新裝載到應用程序中。

如果你采取了適當?shù)脑O計,讓activity能夠正確地處理這些因為屏幕方向而引起的重啟,并能如上面所述的那樣恢復activity的狀態(tài),那么你的應用程序將對生命周期中其它的意外事件更具適應能力。

處理這類重啟的最佳方式,就是在重寫的OnSaveInstanceState()方法中保存狀態(tài),在重寫的OnRestoreInstanceState()或者OnCreate()中恢復狀態(tài)。

這個例子是通過在重寫的OnCreate()方法恢復狀態(tài)的。

實際上,在許多情況下,并不需要總是重寫OnRestoreInstanceState()方法,因為大多數(shù)活動都可以在重寫的OnCreate()方法中直接恢復原來的狀態(tài)。

二、示例2—狀態(tài)保存和恢復

此示例演示了如何保存和恢復用戶旋轉屏幕前后的狀態(tài)。

1、運行截圖

單擊按鈕3次的截圖如下:

技術分享

按【Ctrl】+【F11】后的截圖如下:

技術分享

再次按【Ctrl】+【F11】再次切換為縱向放置。

2、實現(xiàn)步驟

(1)添加ch1102_Layout.axml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas./apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="你單擊了按鈕 0 次"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textViewCount"
        android:layout_margin="20dp"
        android:gravity="center_horizontal" />
    <Button
        android:id="@+id/btn1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="請多次單擊" />
    <TextView
        android:text="提示:【Ctrl】+【F11】用于控制模擬器的屏幕【縱向/橫向】轉換,多次按它觀察屏幕旋轉后單擊按鈕的次數(shù)顯示的情況。"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView2"
        android:layout_margin="20dp" />
</LinearLayout>

(2)添加ch1102Activity.cs文件

using Android.App;
using Android.OS;
using Android.Widget;

namespace MyDemos.SrcDemos
{
    [Activity(Label = "【例11-2】狀態(tài)保存與恢復")]
    public class ch1102Activity : Activity
    {
        private int count = 0;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.ch1102_Layout);
            var txtCount = FindViewById<TextView>(Resource.Id.textViewCount);
            if (savedInstanceState != null)
            {
                count = savedInstanceState.GetInt("counter", 0);
                txtCount.Text = $"你單擊了按鈕 {count} 次";
            }
            var btn1 = FindViewById<Button>(Resource.Id.btn1);
            btn1.Click += (s, e) =>
            {
                count++;
                txtCount.Text = $"你單擊了按鈕 {count} 次";
            };
        }

        protected override void OnSaveInstanceState(Bundle outState)
        {
            outState.PutInt("counter", count);
            base.OnSaveInstanceState(outState);
        }
    }
}

【Android】11.2 通過重寫對應的方法保存和恢復實例的狀態(tài)

標簽:

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多