안드로이드앱 액티비티의 수명주기 생명주기, SharedPreferences, onPause() 저장, onResume() 복원 / Android Studio / 안드로이드 앱만들기 25
액티비티가 만들어지는 순간부터 실행 중지 메모리 해제되는 과정까지
상태 정보를 시스템에서 관리하면서 각각의 상태에 해당하는 메서드를 자동으로 호출한다.
실행 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();
}
}