만족

[Android] static 변수의 값은 영구적으로 보존될까? 본문

[Android] static 변수의 값은 영구적으로 보존될까?

FrontEnd/Android Satisfaction 2020. 4. 9. 23:14

액티비티 A에서 액티비티 B로 데이터를 넘겨주는 방법중 하나는

Intent에 Object를 넣어서 전달하는 방법이다.

 

이 방법은 간단하지만 전달하려는 Object의 크기가 일정 이상이 되면 Exception이 발생하거나 느려지고

거쳐가는 액티비티의 갯수가 많은 경우 매우 번거로운 작업이 될 수 있다.

 

그래서 액티비티간에 object를 전달하지 않고,

새로운 클래스를 만든 다음, 해당 클래스의 static 멤버 변수에 값을 저장하고 필요한 액티비티에서 사용할 수 있도록 해 두었다.

 

public class DataHolder{
	private static List<String> strList= null;
    public static void initStrList(){
    	List<String> strs= new ArrayList();
        strs.add('test');
        strs.add('test');
        strs.add('test');
        strs.add('test');
        strs.add('test');
        strs.add('test');
        strs.add('test');
        strList= strs;
    }
    public static List<String> getStrList(){
    	return strList;
    }
}

DataHolder의 initStrList()는 앱이 시작될 때 가장 먼저 표시되는 액티비티인 SplashActivity에서 호출된다.

public class SplashActivity extends FragmentActivity{
	@Override
    protected void onCreate(Bundle bundle){
    	//...
        DataHolder.init();
       	startActivity(new Intent(this, MainActivity.class);
    }
}
public class MainActivity extends FragmentActivity{
	@Override
    protected void onCreate(Bundle bundle){
    	//...
        
        //never null?
        DataHolder.getStrList();
    }
}

사실 이렇게만 본다면 MainActivity에서 DataHolder.getStrList()가 null일 경우는 절대 없을 것으로 생각할 수 있지만

실제로는 제한적인 상황에서 null이 되기도 한다.

 

이 상황을 인지하지 못하면 NullPointerException이 발생되어 앱이 다운된다.

 

왜 이런일이 발생할까?

우선 안드로이드 OS를 어느 장치에서 많이 사용하는지 생각해보자

 

단연 스마트폰일 것이다.

 

데스크탑에 비해서 스마트폰의 메모리는 상당히 한정적이기 때문에, OS가 이들을 잘 감시하면서 필요하지 않은 메모리를 수시로 회수해 와야만 정상적으로 작동할 것이다.

 

어떤 앱을 실행시키고, 유저가 다른 앱으로 이동하거나 홈 화면으로 이동할 때(앱이 백그라운드 실행 상태가 될 때)

안드로이드 OS는 이들을 우선 정리 대상으로 설정한다.

 

위 그림은 Activity Lifecycle인데, 유저가 백그라운드로 나가서(onStop()) 램이 부족한 상태가 되면

App process killed가 작동되고

다시 유저가 앱을 포그라운드로 이동시키면 마지막 액티비티의 onCreate()부터 다시 시작하게 된다.

 

static variable들도 정리 대상에 포함되기 때문에,

유저가 앱을 백그라운드로 돌려놨다가 다시 포그라운드로 돌아왔을 때 그 변수가 null이 아니라고는 확신할 수 없다.

 

값을 보존하려면 어떻게 해야 할까?

 

영구적으로 데이터를 보존하려면 SharedPreference를 이용한다.

 

SharedPreference는 디스크에 값을 쓰기 때문에 메모리가 정리되어도 다시 get하면 정상적으로 사용할 수 있다.

 

문제는 SharedPreference에서 get,put할 수 있는 값은 String 뿐이라는 것이다.

 

이렇게되면 어쩔 수 없이 해당 오브젝트의 멤버들을 JSON으로 파싱한 다음 String으로 다시 파싱해서 저장한 다음

사용할 때 String 데이터를 받으면, 다시 JSON으로 파싱했다가 Object로 다시 복구해 주어야 한다.

 

좀 귀찮은 방법이긴 하다.

 

다른 방법은 없을까?

 

그림에서 App Process Killed가 이루어지고 난 후, 다시 앱을 포그라운드로 올리면 onCreate()로 이동하는걸 알 수 있다.

 

따라서 액티비티의 onCreate()부분에서 해당 변수값이 보존되어있는지를 체크하고

값이 소실되었을 때의 행동을 명시해주면 앱이 터져나가는 것은 막을 수 있을 것이다.

 

조금 단순무식(?)한 방법을 사용하자면

onCreate에서 static변수가 초기화된 것을 감지하면

Intent에 TOP플래그를 준 다음 앱의 첫 화면(스플래시)으로 강제로 이동시키는 방법도 있다.

 

대신 유저는 좀 빡치겠지만...ㅎㅎ;

 

참조

 

https://stackoverflow.com/questions/4797187/android-static-variable-null-on-low-memory

 



Comments