활동 수명 주기

활동은 Android 애플리케이션의 기본 구성 요소이며 다양한 상태에 존재할 수 있습니다. 활동 수명 주기는 인스턴스화로 시작하고 소멸로 끝나며 그 사이에 많은 상태가 포함됩니다. 활동이 상태를 변경하면 적절한 수명 주기 이벤트 메서드가 호출되어 임박한 상태 변경의 활동을 알리고 해당 변경에 맞게 코드를 실행할 수 있습니다. 이 문서에서는 활동의 수명 주기를 검토하고 이러한 각 상태 변경 중에 활동이 잘 동작하고 신뢰할 수 있는 애플리케이션의 일부가 되는 책임을 설명합니다.

활동 수명 주기 개요

활동은 Android와 관련된 비정상적인 프로그래밍 개념입니다. 기존 애플리케이션 개발에는 일반적으로 애플리케이션을 시작하기 위해 실행되는 정적 기본 메서드가 있습니다. 그러나 Android에서는 상황이 다릅니다. Android 애플리케이션은 애플리케이션 내에서 등록된 모든 작업을 통해 시작할 수 있습니다. 실제로 대부분의 애플리케이션에는 애플리케이션 진입점으로 지정된 특정 작업만 있습니다. 그러나 애플리케이션이 충돌하거나 OS에 의해 종료되는 경우 OS는 마지막 열린 작업 또는 이전 작업 스택 내의 다른 위치에서 애플리케이션을 다시 시작하려고 시도할 수 있습니다. 또한 OS는 활성 상태가 아닐 때 활동을 일시 중지하고 메모리가 부족한 경우 회수할 수 있습니다. 특히 해당 활동이 이전 활동의 데이터에 따라 달라지는 경우 애플리케이션이 활동이 다시 시작되는 경우 해당 상태를 올바르게 복원할 수 있도록 주의해야 합니다.

활동 수명 주기는 OS가 활동의 수명 주기 동안 호출하는 메서드의 컬렉션으로 구현됩니다. 이러한 방법을 통해 개발자는 애플리케이션의 상태 및 리소스 관리 요구 사항을 충족하는 데 필요한 기능을 구현할 수 있습니다.

애플리케이션 개발자는 각 활동의 요구 사항을 분석하여 작업 수명 주기에 의해 노출되는 메서드를 구현해야 하는 방법을 결정하는 것이 매우 중요합니다. 이렇게 하지 않으면 애플리케이션 불안정, 크래시, 리소스 팽창 및 기본 OS 불안정도 발생할 수 있습니다.

이 장에서는 다음을 포함하여 활동 수명 주기를 자세히 살펴봅니다.

  • 활동 상태
  • 수명 주기 메서드
  • 애플리케이션의 상태 유지

이 섹션에는 활동 수명 주기 동안 상태를 효율적으로 저장하는 방법에 대한 실제 예제를 제공하는 연습도 포함되어 있습니다. 이 챕터의 끝부분에는 활동 수명 주기와 Android 애플리케이션에서 이를 지원하는 방법을 이해해야 합니다.

활동 수명 주기

Android 활동 수명 주기는 개발자에게 리소스 관리 프레임워크를 제공하는 활동 클래스 내에 노출되는 메서드 컬렉션으로 구성됩니다. 이 프레임워크를 통해 개발자는 애플리케이션 내에서 각 작업의 고유한 상태 관리 요구 사항을 충족하고 리소스 관리를 적절하게 처리할 수 있습니다.

활동 상태

Android OS는 해당 상태에 따라 활동을 중재합니다. 이를 통해 Android는 더 이상 사용되지 않는 활동을 식별하여 OS가 메모리 및 리소스를 회수할 수 있습니다. 다음 다이어그램은 활동이 수명 동안 겪을 수 있는 상태를 보여 줍니다.

Activity states diagram

이러한 상태는 다음과 같이 4개의 기본 그룹으로 나눌 수 있습니다.

  1. 활성 또는 실행 – 활동 스택의 맨 위라고도 하는 포그라운드에 있는 경우 활동은 활성 또는 실행 중으로 간주됩니다. 이는 Android에서 가장 높은 우선 순위 작업으로 간주되며, 따라서 활동이 디바이스에서 사용할 수 있는 것보다 더 많은 메모리를 사용하려고 하면 UI가 응답하지 않을 수 있으므로 극단적인 상황에서 OS에 의해서만 종료됩니다.

  2. 일시 중지됨 – 디바이스가 절전 모드로 이동하거나 활동이 여전히 표시되지만 전체 크기가 아닌 새 활동 또는 투명 활동으로 부분적으로 숨겨지면 활동이 일시 중지된 것으로 간주됩니다. 일시 중지된 활동은 여전히 활성 상태입니다. 즉, 모든 상태 및 멤버 정보를 기본 있으며 창 관리자에 다시 연결되지 기본. 이는 Android에서 두 번째로 높은 우선 순위 활동으로 간주되며, 따라서 이 작업을 중지하면 활성/실행 활동을 안정적이고 응답성 있게 유지하는 데 필요한 리소스 요구 사항을 충족하는 경우에만 OS에 의해 종료됩니다.

  3. 중지됨/배경 - 다른 활동으로 완전히 가려진 활동은 중지되거나 백그라운드에서 간주됩니다. 중지된 활동은 여전히 가능한 한 오랫동안 상태 및 멤버 정보를 유지하려고 하지만 중지된 활동은 세 가지 상태 중 가장 낮은 우선 순위로 간주되며, 따라서 OS는 우선 순위가 높은 활동의 리소스 요구 사항을 충족하기 위해 먼저 이 상태의 활동을 종료합니다.

  4. 다시 시작 – Android에서 메모리에서 제거될 수 있는 수명 주기에서 일시 중지에서 중지된 작업까지의 작업이 가능합니다. 사용자가 활동으로 다시 이동하는 경우 다시 시작하고 이전에 저장된 상태로 복원한 다음 사용자에게 표시해야 합니다.

구성 변경에 대한 응답으로 활동 다시 만들기

문제를 더 복잡하게 만들기 위해 Android는 구성 변경이라는 혼합에서 한 번 더 렌치를 throw합니다. 구성 변경은 디바이스가 회전될 때(및 활동이 가로 또는 세로 모드로 다시 빌드되어야 하는 경우), 키보드가 표시될 때(및 활동 자체의 크기를 조정할 수 있는 기회가 제공됨), 또는 장치가 도크에 배치될 때와 같이 활동 구성이 변경될 때 발생하는 신속한 활동 소멸/다시 생성 주기입니다. 다른 사람의 사이에서.

구성 변경으로 인해 작업을 중지하고 다시 시작하는 동안 발생하는 것과 동일한 활동 상태 변경이 계속 발생합니다. 그러나 구성을 변경하는 동안 애플리케이션이 응답성이 뛰어나고 성능이 좋은지 확인하려면 가능한 한 빨리 처리하는 것이 중요합니다. 이 때문에 Android에는 구성을 변경하는 동안 상태를 유지하는 데 사용할 수 있는 특정 API가 있습니다. 이 내용은 수명 주기 전체의 상태 관리 섹션의 뒷부분에서 설명합니다.

활동 수명 주기 메서드

Android SDK 및 확장에서 Xamarin.Android 프레임워크는 애플리케이션 내의 활동 상태를 관리하기 위한 강력한 모델을 제공합니다. 활동의 상태가 변경되면 해당 활동에 대한 특정 메서드를 호출하는 OS에서 활동을 알 수 있습니다. 다음 다이어그램에서는 활동 수명 주기와 관련하여 이러한 메서드를 보여 줍니다.

Activity Lifecycle flowchart

개발자는 활동 내에서 이러한 메서드를 재정의하여 상태 변경을 처리할 수 있습니다. 그러나 모든 수명 주기 메서드는 UI 스레드에서 호출되며 OS가 현재 활동 숨기기, 새 활동 표시 등과 같은 다음 UI 작업을 수행하지 못하도록 차단한다는 점에 유의해야 합니다. 따라서 이러한 메서드의 코드는 애플리케이션이 잘 수행되도록 하려면 가능한 한 짧아야 합니다. 장기 실행 작업은 백그라운드 스레드에서 실행되어야 합니다.

이러한 각 수명 주기 메서드와 해당 용도를 살펴보겠습니다.

OnCreate

OnCreate 는 활동을 만들 때 호출되는 첫 번째 메서드입니다. OnCreate 는 다음과 같은 활동에 필요할 수 있는 시작 초기화를 수행하기 위해 항상 재정의됩니다.

  • 보기 만들기
  • 변수 초기화
  • 정적 데이터를 목록에 바인딩

OnCreate는 번들 매개 변수를 사용합니다. 이 매개 변수는 작업 간에 상태 정보 및 개체를 저장하고 전달하기 위한 사전입니다. 번들은 null이 아닌 경우 활동이 다시 시작되고 이전 인스턴스에서 상태를 복원해야 했음을 나타냅니다. 다음 코드는 번들에서 값을 검색하는 방법을 보여 줍니다.

protected override void OnCreate(Bundle bundle)
{
   base.OnCreate(bundle);

   string intentString;
   bool intentBool;

   if (bundle != null)
   {
      intentString = bundle.GetString("myString");
      intentBool = bundle.GetBoolean("myBool");
   }

   // Set our view from the "main" layout resource
   SetContentView(Resource.Layout.Main);
}

완료되면 OnCreate Android에서 호출 OnStart합니다.

OnStart

OnStart 는 완료된 후 OnCreate 시스템에서 항상 호출됩니다. 활동 내에서 보기의 현재 값을 새로 고치는 등 활동이 표시되기 바로 전에 특정 작업을 수행해야 하는 경우 활동이 이 메서드를 재정의할 수 있습니다. Android는 이 메서드 바로 후에 호출 OnResume 됩니다.

OnResume

작업이 사용자와 상호 작용을 시작할 준비가 되면 시스템에서 OnResume를 호출합니다. 활동은 다음과 같은 작업을 수행하도록 이 메서드를 재정의해야 합니다.

  • 프레임 속도 향상(게임 개발의 일반적인 작업)
  • 애니메이션 시작
  • GPS 업데이트 수신 대기
  • 관련 경고 또는 대화 상자 표시
  • 외부 이벤트 처리기 연결

예를 들어 다음 코드 조각은 카메라를 초기화하는 방법을 보여줍니다.

protected override void OnResume()
{
    base.OnResume(); // Always call the superclass first.

    if (_camera==null)
    {
        // Do camera initializations here
    }
}

OnResume작업이 다시 시작되면 실행 OnPause 되도록 보장되는 유일한 수명 주기 메서드이므로 수행되는 모든 작업은 OnPause 수행되지 않아야 OnResume하기 때문에 중요합니다.

OnPause

OnPause 는 시스템이 활동을 백그라운드로 배치하려고 하거나 활동이 부분적으로 가려질 때 호출됩니다. 활동은 다음을 수행해야 하는 경우 이 메서드를 재정의해야 합니다.

  • 저장되지 않은 변경 내용을 영구 데이터에 커밋

  • 리소스를 사용하는 다른 개체를 삭제하거나 클린

  • 프레임 속도 감소 및 애니메이션 일시 중지

  • 외부 이벤트 처리기 또는 알림 처리기(즉, 서비스에 연결된 처리기)의 등록을 취소합니다. 작업 메모리 누수 방지를 위해 이 작업을 수행해야 합니다.

  • 마찬가지로 활동에 대화 상자 또는 경고가 표시되면 메서드를 사용하여 클린 .Dismiss() 합니다.

예를 들어 다음 코드 조각은 일시 중지된 동안 활동이 카메라를 사용할 수 없으므로 카메라를 해제합니다.

protected override void OnPause()
{
    base.OnPause(); // Always call the superclass first

    // Release the camera as other activities might need it
    if (_camera != null)
    {
        _camera.Release();
        _camera = null;
    }
}

다음 두 가지 수명 주기 메서드가 호출 OnPause될 수 있습니다.

  1. OnResume 는 활동을 포그라운드로 반환할 경우 호출됩니다.
  2. OnStop 는 활동이 백그라운드에 배치되는 경우 호출됩니다.

OnStop

활동이 사용자에게 더 이상 표시되지 않을 때 OnStop 이 호출됩니다. 이 문제는 다음 중 하나가 발생할 때 발생합니다.

  • 새 활동이 시작되고 이 활동을 은폐하고 있습니다.
  • 기존 활동을 포그라운드로 가져오고 있습니다.
  • 활동이 제거되고 있습니다.

OnStop 는 Android가 리소스에 부족하고 활동을 제대로 백그라운드로 설정할 수 없는 경우와 같이 메모리가 부족한 상황에서 항상 호출되지 않을 수 있습니다. 이러한 이유로 소멸 활동을 준비할 OnStop 때 호출을 받지 않는 것이 가장 좋습니다. 이 OnDestroy 수명 주기 이후에 호출될 수 있는 다음 수명 주기 메서드는 활동이 사라지거나 OnRestart 활동이 사용자와 상호 작용하기 위해 돌아오는 경우입니다.

OnDestroy

OnDestroy 는 작업 인스턴스가 제거되고 메모리에서 완전히 제거되기 전에 작업 인스턴스에서 호출되는 최종 메서드입니다. 극단적인 상황에서 Android는 활동을 호스팅하는 애플리케이션 프로세스를 종료하여 OnDestroy 호출되지 않을 수 있습니다. 대부분의 활동은 대부분의 클린 및 메서드에서 수행되었기 때문에 이 메서드를 OnPauseOnStop 구현하지 않습니다. OnDestroy 이 메서드는 일반적으로 리소스를 누수할 수 있는 장기 실행 작업을 클린 위해 재정의됩니다. 이 예제는 .에서 OnCreate시작된 백그라운드 스레드일 수 있습니다.

활동이 제거된 후 호출되는 수명 주기 메서드는 없습니다.

OnRestart

OnRestart 는 활동이 중지된 후 다시 시작하기 전에 호출됩니다. 이 예제의 좋은 예는 사용자가 애플리케이션에서 작업하는 동안 홈 단추를 누를 때입니다. 이 경우 OnPauseOnStop 메서드가 호출되고 활동이 백그라운드로 이동되지만 제거되지는 않습니다. 사용자가 작업 관리자 또는 유사한 애플리케이션을 사용하여 애플리케이션을 복원하는 경우 Android는 활동의 메서드를 OnRestart 호출합니다.

에서 구현해야 하는 논리 종류에 대한 일반적인 지침은 OnRestart없습니다. 활동이 OnStart 만들어지는지 또는 다시 시작되든 관계없이 항상 호출되므로 활동에 필요한 모든 리소스를 초기화하지 않고 OnRestart초기화OnStart해야 합니다.

다음에 OnRestart 호출된 다음 수명 주기 메서드는 .입니다 OnStart.

뒤로 및 홈

많은 Android 디바이스에는 "뒤로" 단추와 "홈" 단추라는 두 개의 고유한 단추가 있습니다. 이 예제는 Android 4.0.3의 다음 스크린샷에서 확인할 수 있습니다.

Back and Home buttons

두 단추 사이에는 애플리케이션을 백그라운드에 배치하는 것과 동일한 효과가 있는 것처럼 보이지만 미묘한 차이가 있습니다. 사용자가 뒤로 단추를 클릭하면 Android에 작업이 완료되었다는 것을 알립니다. Android는 활동을 삭제합니다. 반면, 사용자가 홈 단추를 클릭하면 활동이 단지 백그라운드에 배치됩니다. Android는 활동을 종료하지 않습니다.

수명 주기 동안 상태 관리

작업이 중지되거나 제거되면 시스템은 나중에 리하일레이션을 위해 활동 상태를 저장할 수 있는 기회를 제공합니다. 이 저장된 상태를 인스턴스 상태라고 합니다. Android는 활동 수명 주기 동안 인스턴스 상태를 저장하는 세 가지 옵션을 제공합니다.

  1. Android에서 Dictionary상태를 저장하는 데 사용할 번들에 기본 값을 저장합니다.

  2. 비트맵과 같은 복합 값을 보유하는 사용자 지정 클래스를 만듭니다. Android는 이 사용자 지정 클래스를 사용하여 상태를 저장합니다.

  3. 구성 변경 수명 주기를 우회하고 활동에서 상태를 기본 대한 완전한 책임을 져야 합니다.

이 가이드에서는 처음 두 가지 옵션을 설명합니다.

번들 상태

인스턴스 상태를 저장하는 기본 옵션은 번들로 알려진 키/값 사전 개체를 사용하는 것입니다. 메서드가 번들을 매개 변수로 전달한다는 OnCreate 작업을 만들 때 이 번들을 사용하여 인스턴스 상태를 복원할 수 있습니다. 키/값 쌍(예: 비트맵)으로 빠르게 또는 쉽게 직렬화되지 않는 더 복잡한 데이터에 번들을 사용하지 않는 것이 좋습니다. 오히려 문자열과 같은 간단한 값에 사용해야 합니다.

활동은 번들에서 인스턴스 상태를 저장하고 검색하는 데 도움이 되는 메서드를 제공합니다.

  • OnSaveInstanceState – 활동이 제거될 때 Android에서 호출됩니다. 활동은 키/값 상태 항목을 유지해야 하는 경우 이 메서드를 구현할 수 있습니다.

  • OnRestoreInstanceState – 메서드가 완료된 후에 OnCreate 호출되며 초기화가 완료된 후 활동이 상태를 복원할 수 있는 또 다른 기회를 제공합니다.

다음 다이어그램에서는 이러한 메서드를 사용하는 방법을 보여 줍니다.

Bundle states flowchart

OnSaveInstanceState

작업이 중지되면 OnSaveInstanceState 가 호출됩니다. 활동에서 상태를 저장할 수 있는 번들 매개 변수가 수신됩니다. 디바이스에서 구성 변경이 발생하는 경우 작업은 전달된 개체를 사용하여 Bundle 재정의하여 활동 상태를 유지할 수 있습니다 OnSaveInstanceState. 예를 들어, 다음 코드를 고려하세요.

int c;

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);

  this.SetContentView (Resource.Layout.SimpleStateView);

  var output = this.FindViewById<TextView> (Resource.Id.outputText);

  if (bundle != null) {
    c = bundle.GetInt ("counter", -1);
  } else {
    c = -1;
  }

  output.Text = c.ToString ();

  var incrementCounter = this.FindViewById<Button> (Resource.Id.incrementCounter);

  incrementCounter.Click += (s,e) => {
    output.Text = (++c).ToString();
  };
}

위의 코드는 명명된 단추를 클릭할 때 명명 cincrementCounter 된 정수가 증가하여 결과를 명명output된 값으로 TextView 표시합니다. 구성 변경이 발생하는 경우(예: 디바이스가 회전될 때) 위 코드는 아래 그림과 같이 값 c 이 손실되기 null때문 bundle 입니다.

Display does not show previous value

이 예제의 값을 유지하기 위해 작업은 재정OnSaveInstanceStatec 하여 아래와 같이 번들에 값을 저장합니다.

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

이제 디바이스가 새 방향으로 회전하면 정수가 번들에 저장되고 줄과 함께 검색됩니다.

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

참고 항목

뷰 계층의 상태도 저장할 수 있도록 항상 기본 구현 OnSaveInstanceState 을 호출하는 것이 중요합니다.

상태 보기

재정의 OnSaveInstanceState 는 위 예제의 카운터와 같이 방향 변경 내용 간에 임시 데이터를 작업에 저장하는 적절한 메커니즘입니다. 그러나 기본 구현 OnSaveInstanceState 은 각 보기에 ID가 할당된 한 모든 보기에 대해 UI에 임시 데이터를 저장하는 것을 처리합니다. 예를 들어 애플리케이션에 EditText 다음과 같이 XML에 정의된 요소가 있다고 가정합니다.

<EditText android:id="@+id/myText"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"/>

컨트롤에 EditText 할당되어 있으므로 id 사용자가 일부 데이터를 입력하고 디바이스를 회전할 때 아래와 같이 데이터가 계속 표시됩니다.

Data is preserved in landscape mode

OnRestoreInstanceState

OnRestoreInstanceState 는 이후에 OnStart호출됩니다. 이전 동안 OnSaveInstanceState번들에 이전에 저장된 상태를 복원할 수 있는 기회를 제공합니다. 그러나 이는 제공된 OnCreate것과 동일한 번들입니다.

다음 코드는 다음에서 상태를 복원하는 방법을 보여 줍니다.OnRestoreInstanceState

protected override void OnRestoreInstanceState(Bundle savedState)
{
    base.OnRestoreInstanceState(savedState);
    var myString = savedState.GetString("myString");
    var myBool = savedState.GetBoolean("myBool");
}

이 메서드는 상태를 복원해야 하는 시기를 유연하게 제공하기 위해 존재합니다. 인스턴스 상태를 복원하기 전에 모든 초기화가 완료될 때까지 기다리는 것이 더 적절한 경우도 있습니다. 또한 기존 활동의 하위 클래스는 인스턴스 상태에서 특정 값만 복원하려고 할 수 있습니다. 대부분의 활동은 제공된 번들을 사용하여 상태를 복원할 수 있으므로 대부분의 경우 재정 OnRestoreInstanceState의할 OnCreate필요가 없습니다.

상태를 사용하여 저장하는 예제는 Bundle연습 - 작업 상태 저장을 참조하세요.

Bundle 제한 사항

일시적 데이터를 쉽게 저장할 수 있지만 OnSaveInstanceState 다음과 같은 몇 가지 제한 사항이 있습니다.

  • 모든 경우에 호출되지 않습니다. 예를 들어 홈 또는 뒤로를 눌러 작업을 종료하면 호출되지 않습니다OnSaveInstanceState.

  • 전달된 OnSaveInstanceState 번들은 이미지와 같은 큰 개체용으로 설계되지 않았습니다. 큰 개체의 경우 아래에 설명된 대로 OnRetainNonConfigurationInstance에서 개체를 저장하는 것이 좋습니다.

  • 번들을 사용하여 저장한 데이터는 직렬화되므로 지연이 발생할 수 있습니다.

번들 상태는 메모리를 많이 사용하지 않는 간단한 데이터에 유용하지만 구성이 아닌 인스턴스 데이터는 더 복잡한 데이터 또는 웹 서비스 호출 또는 복잡한 데이터베이스 쿼리와 같이 검색하는 데 비용이 많이 드는 데이터에 유용합니다. 구성되지 않은 인스턴스 데이터는 필요에 따라 개체에 저장됩니다. 다음 섹션에서는 구성 변경을 통해 더 복잡한 데이터 형식을 유지하는 방법을 소개합니다 OnRetainNonConfigurationInstance .

복잡한 데이터 유지

Android는 번들에 데이터를 유지하는 것 외에도 OnRetainNonConfigurationInstance재정의 Java.Lang.Object 하고 유지할 데이터가 포함된 인스턴스를 반환하여 데이터 저장을 지원합니다. 상태를 저장하는 데 사용할 OnRetainNonConfigurationInstance 때의 두 가지 주요 이점은 다음과 같습니다.

  • 메모리가 이 개체를 유지하므로 반환된 OnRetainNonConfigurationInstance 개체는 더 크고 복잡한 데이터 형식에서 잘 수행됩니다.

  • 메서드는 OnRetainNonConfigurationInstance 필요할 때만 요청 시 호출됩니다. 수동 캐시를 사용하는 것보다 경제적입니다.

사용 OnRetainNonConfigurationInstance 은 웹 서비스 호출과 같이 데이터를 여러 번 검색하는 데 비용이 많이 드는 시나리오에 적합합니다. 예를 들어 Twitter를 검색하는 다음 코드를 고려합니다.

public class NonConfigInstanceActivity : ListActivity
{
  protected override void OnCreate (Bundle bundle)
  {
    base.OnCreate (bundle);
    SearchTwitter ("xamarin");
  }

  public void SearchTwitter (string text)
  {
    string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q={0}&rpp=10&include_entities=false&" + "result_type=mixed", text);

    var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl));
    httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq);
  }

  void ResponseCallback (IAsyncResult ar)
  {
    var httpReq = (HttpWebRequest)ar.AsyncState;

    using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) {
      ParseResults (httpRes);
    }
  }

  void ParseResults (HttpWebResponse httpRes)
  {
    var s = httpRes.GetResponseStream ();
    var j = (JsonObject)JsonObject.Load (s);

    var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult ["text"].ToString ()).ToArray ();

    RunOnUiThread (() => {
      PopulateTweetList (results);
    });
  }

  void PopulateTweetList (string[] results)
  {
    ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
  }
}

이 코드는 JSON으로 서식이 지정된 웹에서 결과를 검색하고 구문 분석한 다음, 다음 스크린샷과 같이 목록에 결과를 표시합니다.

Results displayed on screen

구성 변경이 발생하면(예: 디바이스를 회전할 때) 코드가 프로세스를 반복합니다. 원래 검색된 결과를 다시 사용하고 불필요한 중복 네트워크 호출을 일으키지 않으려면 아래와 같이 결과를 저장하는 데 사용할 OnRetainNonconfigurationInstance 수 있습니다.

public class NonConfigInstanceActivity : ListActivity
{
  TweetListWrapper _savedInstance;

  protected override void OnCreate (Bundle bundle)
  {
    base.OnCreate (bundle);

    var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper;

    if (tweetsWrapper != null) {
      PopulateTweetList (tweetsWrapper.Tweets);
    } else {
      SearchTwitter ("xamarin");
    }

    public override Java.Lang.Object OnRetainNonConfigurationInstance ()
    {
      base.OnRetainNonConfigurationInstance ();
      return _savedInstance;
    }

    ...

    void PopulateTweetList (string[] results)
    {
      ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
      _savedInstance = new TweetListWrapper{Tweets=results};
    }
}

이제 디바이스가 회전되면 속성에서 LastNonConfiguartionInstance 원래 결과가 검색됩니다. 이 예제에서 결과는 포함된 트윗으로 string[] 구성됩니다. OnRetainNonConfigurationInstanceJava.Lang.Object 반환 string[] 해야 하므로 아래와 같이 서브클래스가 Java.Lang.Object있는 클래스에 래핑됩니다.

class TweetListWrapper : Java.Lang.Object
{
  public string[] Tweets { get; set; }
}

예를 들어 반환 OnRetainNonConfigurationInstance 된 개체로 사용 TextView 하려고 하면 아래 코드에 설명된 대로 활동이 누출됩니다.

TextView _textView;

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);

  var tv = LastNonConfigurationInstance as TextViewWrapper;

  if(tv != null) {
    _textView = tv;
    var parent = _textView.Parent as FrameLayout;
    parent.RemoveView(_textView);
  } else {
    _textView = new TextView (this);
    _textView.Text = "This will leak.";
  }

  SetContentView (_textView);
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()
{
  base.OnRetainNonConfigurationInstance ();
  return _textView;
}

이 섹션에서는 간단한 상태 데이터를 함께 유지하고 더 복잡한 데이터 형식OnRetainNonConfigurationInstanceBundle유지하는 방법을 알아보았습니다.

요약

Android 활동 수명 주기는 애플리케이션 내에서 활동을 상태 관리하기 위한 강력한 프레임워크를 제공하지만 이해하고 구현하기가 어려울 수 있습니다. 이 장에서는 해당 수명 동안 활동이 발생할 수 있는 다양한 상태와 해당 상태와 연결된 수명 주기 메서드를 소개했습니다. 다음으로 이러한 각 메서드에서 수행해야 하는 논리 종류에 대한 지침이 제공되었습니다.