모바일/안드로이드앱

안드로이드앱 액티비티의 수명주기 생명주기, SharedPreferences, onPause() 저장, onResume() 복원 / Android Studio / 안드로이드 앱만들기 25

yy_dd2 2021. 3. 15. 20:58
반응형

액티비티가 만들어지는 순간부터 실행 중지 메모리 해제되는 과정까지

상태 정보를 시스템에서 관리하면서 각각의 상태에 해당하는 메서드를 자동으로 호출한다.

실행 Running : 화면상에 액티비티가 보이면서 실행되어 있는 상태, 액티비티 스택의 최상위에 있다, 포커스 가지고 있다

일시정지 Paused : 사용자에게 보이지만 다른 액티비티가 위에 있어 포커스가 없다, 대화상자가 위에 있어 일부가 가려진 경우 해당

중지 Stopped : 다른 액티비티에 의해 완전히 가려져 보이지 않는 상태

 

 

상태에 따른 메서드

 

onCreate()

- 액티비티가 처음 만들어질때 호출된다

- 화면에 보이는 뷰들의 일반적인 상태 설정

- 이전 상태가 저장된 경우 번들 객체를 참조해 이전 상태 복원 가능 

- 이 메서드 다음에는 항상 start()메서드가 호출

 

onStart()

- 액티비티가 화면에 보이기 바로 전에 호출

- 앤티비티가 화면 상에 보이면 이 메서드 다음에 onResume() 메서드 호출

- 액티비티가 화면에 가려지게 되면 이 메서드 다음에 onStop() 메서드 호출

 

onResume()

- 액티비티가 사용자와 상호작용하기 전에 호출됨

 

onRestart()

- 액티비티가 중지된 이후에 호출되는 메서드 다시 시작되기 바로 전에 호출됨

- 이 메서드 다음에 한상 onStart() 메서드가 호출됨

 

onPause()

- 또 다른 액티비티를 시작 하려고 할 때 호출됨

- 저장되지 않은 데이터를 저장소에 저장하거나 애니메이션 중인 작업을 중지하는 등의 기능 수행을 하는 메서드

- 이 메서드가 리턴하기 전에는 다음 액티비티가 시작될 수 없으므로 이 작업은 매우 빨리 수행된 후 리턴이 되어야함

- 액티비티가 이 상태에 들어가면 시스템은 액티비티를 강제 종료 할 수 있음

 

onStop()

- 액티비티가 사용자에게 더 이상 보이지 않을 때 호출됨

- 액티비티가 소멸되거나 또 다른 액티비티가 화면을 가릴 때 호출됨

- 액티비티가 이 상태에 들어가면 시스템은 액티비티를 강제 종료 할 수 있음

 

onDestroy()

- 액티비티가 소멸되어 없어 지기 전에 호출 

- 이 메서드는 액티비티가 받는 마지막 호출이 됨

- 액티비티가 앱에 의해 종료되거나 (finsh() 메서드 호출) 시스템이 강제로 종료시키는 경우에 호출될 수 있음

- 위의 두 가지 경우를 구분할 때 isFinishing() 메서드를 이용함

- 액티비티가 이 상테에 들어가면 시스템은 액티비티를 강제 종료할 수 있음

 

onSaveInstanceStarte() 데이터를 임시로 저장

- 이메서드의 파라미터로 전달되는 번들 객체를 이용해 데이터를 저장하면 onCreate() 메서드나 onRestoreInstanceStarte() 메서드로 저장 했던 데이터가 전달 된다.

- 이 방식을 사용하면 앱이 강제 종료되거나 비정상 종료된 이후에 앱이 재실행되었을 때도 그 상태 그대로 보일 수 있도록 만들어 줍니다.

 


액티비티의 수명주기 확인하기

 

1. SampleLifeCycle 프로젝트 생성

 

2. activirty_main.xml 파일을 열고 텍스트뷰는 삭제한 후 버튼 하나와 텍스트뷰 하나를 추가한다.

- 버튼에는 ' 메뉴 화면 띄우기'  

 

3. 메뉴 액티비티추가

- 버튼을 누르면 메뉴 액티비티를 띄우도록 소스 코드 수정

- 메뉴 액티비티는 돌아가기 버튼 추가

- 버튼 누르면 이전 화면으로 돌아가기

(책에서 이제 이정도는 그냥 만들수있지 않냐며... 만들래서 코드작성했다 자동완성 만세)

 

4. 화면에 따른 onStart, onStop, onResume, onPause, onDestroy 작동확인

더보기
package com.togapp.samplelifecycle;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_MENU = 101;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        println("onCreate() 호출");
        //Toast.makeText(this, "onCreate() 호출", Toast.LENGTH_SHORT).show();

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getApplicationContext(), MenuActivity.class);
                startActivityForResult(intent, REQUEST_CODE_MENU);
            }
        });
    }


    @Override
    protected void onStart() {
        super.onStart();
        println("onStart() 호출");
    }

    @Override
    protected void onStop() {
        super.onStop();
        println("onStop() 호출");
        //Toast.makeText(this, "onStop() 호출", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        println("onDestroy() 호출");
        //Toast.makeText(this, "onDestroy() 호출", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        println("onPause() 호출");
        //Toast.makeText(this, "onPause() 호출", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        println("onResume() 호출");
        //Toast.makeText(this, "onResume() 호출", Toast.LENGTH_SHORT).show();
    }

    public void println(String data){
        Toast.makeText(this,data,Toast.LENGTH_LONG).show();
        Log.d("main", data);
    }

}

 

액티비티의 수명주기 메서드의 순서를 정리하면

onCreate (화면보일 때 시작) ->

onStart ->

onResume (화면보일 때 끝) ->

onPause (화면 끝날때 시작) ->

onStop ->

onDestroy

 

5. mainActivity.java

앱이 종료된 후 다시 실행했을때 데이터가 그대로 있도록 하기

- activity_main.xml 에 editText 추가 'id = nameInput'으로 설정함

- SharedPreferences의 저장 복원 메서드 호출하기

- onPause() 메서드에서 데이터를 저장

- onResume() 메서드에서 데이터를 복원

 

//////// 생략
    EditText nameInput;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        nameInput = findViewById(R.id.nameInput);
//////// 생략

EditText 변수 설정해서 찾아와주고 (참고로 Do it 책이나 코드 작성된데에 찾아오라는 코드가 없었음 이거때문에 오류남)

 

//////// 생략
    protected void restoreState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        if ((pref != null) && (pref.contains("name")) ) {
            String name = pref.getString("name", "");
            nameInput.setText(name);
        }
    }


    protected void saveState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("name", nameInput.getText().toString());
        // editor.commit();
        editor.apply();

    }

    protected  void clearState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.clear();
        // editor.commit();
        editor.apply();
    }
}   // public class MainActivity extends AppCompatActivity { 끝

- onPause() 메서드에서 데이터를 저장

- onResume() 메서드에서 데이터를 복원

메서드 안에 들어갈 메서드 만들기

 

//////// 생략
    @Override
    protected void onPause() {
        super.onPause();
        //println("onPause() 호출");
        Toast.makeText(this, "onPause() 호출", Toast.LENGTH_SHORT).show();
        // 현재 입력상자에 입력된 데이터를 저장
        saveState();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //println("onResume() 호출");
        Toast.makeText(this, "onResume() 호출", Toast.LENGTH_SHORT).show();
        // 설정된 정보의 저장된 데이터 복원
        restoreState();

    }
//////// 생략

saveState();

restpreState();

 

 

연속적으로 써야하는걸 만들때 아래처럼 사용하면 편리할거 같음 정리한거 메모 기억하기

 

public class MainActivity extends AppCompatActivity {

  static private String SHARE_NAME = "SHARE_PREF";
  static SharedPreferences sharePref = null;
  static SharedPreferences.Editor editor = null;



  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    sharePref = getSharedPreferences(SHARE_NAME, MODE_PRIVATE);
    editor = sharePref.edit();
    
    nameInput = findViewById(R.id.nameInput);

    /// 생략
}


  protected void saveState() {

    editor.putBoolean("boolean", true);
    editor.putFloat("floatRate", 1.22f);
    editor.putInt("nameValue", 200);
    editor.putString("name", "copycoding");
    editor.apply();

  }
  
} // public class MainActivity extends AppCompatActivity { 끝

 

 

 

더보기
package com.togapp.samplelifecycle;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_MENU = 101;
    EditText nameInput;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        nameInput = findViewById(R.id.nameInput);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getApplicationContext(), MenuActivity.class);
                startActivityForResult(intent, REQUEST_CODE_MENU);
                //startActivity(intent);
            }
        });

        println("onCreate() 호출");
        //Toast.makeText(this, "onCreate() 호출", Toast.LENGTH_SHORT).show();
    }


    @Override
    protected void onStart() {
        super.onStart();
        println("onStart() 호출");
        //Toast.makeText(this, "onStart 호출됨", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        println("onStop() 호출");
        //Toast.makeText(this, "onStop() 호출", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        println("onDestroy() 호출");
        //Toast.makeText(this, "onDestroy() 호출", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //println("onPause() 호출");
        Toast.makeText(this, "onPause() 호출", Toast.LENGTH_SHORT).show();
        // 현재 입력상자에 입력된 데이터를 저장
        saveState();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //println("onResume() 호출");
        Toast.makeText(this, "onResume() 호출", Toast.LENGTH_SHORT).show();
        // 설정된 정보의 저장된 데이터 복원
        restoreState();

    }

    public void println(String data) {
        Toast.makeText(this,data,Toast.LENGTH_LONG).show();
        Log.d("main", data);
    }

    protected void restoreState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        if ((pref != null) && (pref.contains("name")) ) {
            String name = pref.getString("name", "");
            nameInput.setText(name);
        }
    }


    protected void saveState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("name", nameInput.getText().toString());
        // editor.commit();
        editor.apply();

    }

    protected  void clearState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.clear();
        // editor.commit();
        editor.apply();
    }

}   // public class MainActivity extends AppCompatActivity { 끝

 

 

++ 책에는 restoreState() 메서드 설명에 저장된 데이터를 가져와서 토스트 메시지로 보여준다는데 없어서 코드 추가했음....(점점 책의 오류가 눈에 보이기 시작함)

    protected void restoreState() {
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        if ((pref != null) && (pref.contains("name")) ) {
            String name = pref.getString("name", "");
            nameInput.setText(name);
            Toast.makeText(this,name,Toast.LENGTH_LONG).show();
        }
    }

 

 

 

반응형