마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Rotate시 private variable 유지

0 추천

안녕하세요,

 

non-static변수

private variable에 대하여 질문을 올리고자 합니다.

 

우선 큰 그림으로는

부모 Activity인 A가 자식 Activity인 B를 호출합니다.

 

B의 구성은 대충

public class B extends Activity {

    private boolean variable;

    private CClass cObject;

 

    @Override

    public void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstaceState);

        Log.e("asdf", "" + variable);

        ...

 

        cObject = savedInstaceState != null? (CClass) getLastNonConfigurationInstance() : new CClass() {

            CClass.onTouchEvent(MotionEvent event) {

                Log.e("asdf", "" + variable);

            }

        };

    }

   

    public Object onRetainNonConfigurationInstance() {

        CClass tempCObject = cObject;

        this.cObject = null;

 

        return tempCObject;

    }

 

    ....

}

로 되어있습니다.

 

처음 B Activity 실행 시 Log에는 false가 찍힙니다.

이후 여러 동작을 통해 variable은 true혹은 false로 바뀌게 되는데,

이때에는 cObject.onTouchEvent()의 Log에서는 현재 variable값에 적용된 값이 찍힙니다.

 

가장 마지막으로 variabletrue로 저장 후,

화면 회전시 onCreate()에서 호출된 Log를 보면 false로 찍힙니다.

이후부터는 cObject.onTouchEvent()의 Log에서는 현재 variable과는 다른 false값만이 찍힙니다.

(이전 변수를 가져온 cObject외에 다른 함수에서 Log시에는 현재 variable값이 찍힙니다.)

(하지만, 회전 이전과 이후의 System.identityHashCode(vriable)의 값을 동일 하더라구요...)

 

이러한 상황을

private boolean variable; 가 아닌

private static boolean variable; 로 선언하면 발생하지 않습니다.

 

=======================

화면 회전시 해당 클레스에서 private로 선언한 변수를 재생성하지 않고 전달받아 계속 사용하는 방법이 따로 있는 것 입니까?

 

긴 글 읽어주셔서 감사합니다.

nkSong (1,000 포인트) 님이 2017년 9월 4일 질문
nkSong님이 2017년 9월 4일 수정

1개의 답변

0 추천
 
채택된 답변
public Object onRetainNonConfigurationInstance() {

상기 함수 위에 @Override가 없으면, 넣어주세요.
Will Kim (43,170 포인트) 님이 2017년 9월 5일 답변
nkSong님이 2017년 9월 5일 채택됨
답변 감사드립니다.

오버라이드 한 메소드 입니다... ㅎ....ㅜ
그럼,
cObject = savedInstaceState != null? (CClass) getLastNonConfigurationInstance() : new CClass() {

상기 부분을
cObject = (CClass) getLastNonConfigurationInstance();
if (cObject == null) {
    cObject = new CClass();
}

로 바꾸어 보세요.
감사합니다.

해당 코드로 하였을 경우, 별 차이는 없었습니다.

첫 실행시 getLastNonConfigurationInstance()를 통하여 넘어온 객체가 없기에 생성해주는 문장이 실행된것 같구요,

화면 회전시 getLastNonConfigurationInstance()를 통하여 회전하기 이전의 cObject를 받아왔습니다만, 여전히 이전 cObject의 variable은 회전 이후의 variable과 다르게 작동되고 있습니다.. ㅜ

화면 회전시에 B클래스 내의 private 변수는 재생성 되는것인가요....?

해당 코드로 수정후에도 static을 붙여 선언하면 로테이트 이후에 받아온 이전 cObject의 variable과 로테이트 후의 variable은 동일한 값으로 동작되고 있습니다...
아.. 질문을 제가 잘 이해를 못했군요.
화면 회전시 Activity 자체가 recreation됩니다.
static으로 하지 않을 이유가 있나요?

Manifest에서 지정하는 방법도 있는데, 그것보다는 static으로 하라고 조언이 나오네요.
앗, recreation하면 variable들도 재생성 되는 것인가요!?

static으로 하면 그 재생성 되는것을 막는것이구요!?

ㅜㅜ

인터넷에서 찾아보니 잘 모르겠습니다만, static으로 정적변수를 생성하면, memory를 계속 차지하고 있으며, 작업시에 수많은 에러, 문제점등을 포함/유발시킨다고 쓰여있길래 최대한 안쓰려 해보았습니다...

우선은 static으로 사용을 해야하는 것이겠네요..

답변 감사드립니다~!
static에 간단한 값들, 크지 않은 데이터는 저장하는 것은 상관없습니다.
만약에 bitmap, 덩치큰 파일같은 객체를 보관하는 것은 문제가 있죠.

또한 자바로 서버를 개발할 때는 static은 피하는게 좋습니다.
서버에서 동작하는 서비스들이나 웹 서비스들은 1년 365일 실행되기 때문에, 한번 수행하는데 몇십바이트씩 생성이 되고, 하루에 10,000번 정도 접속이 이루어지고, 365일 내내 수행이 된다면, 몇십 바이트도 쌓이면 언젠가 메모리가 부족해 지죠.

반면, 클라이언트는 어차피 사용자가 앱을 죽이기도 하고, 안드로이드가 죽이기도 하고, 재부팅도 서버에 비해서는 자주 하는 편이기 때문에, 그정도의 문제는 상관없습니다.

원칙적으로 이야기 한다면,
Static이던 아니던, 변수가 언제 생성이 되고, 언제 소멸하는지 Life Cycle를 개발자가 파악하고 있느냐 아니냐가 중요합니다.
문제가 되는 경우, 대부분 유사한 변수들을 마구 선언하고, 대입하고, 나중에 쓰지도 않는 변수들이 남발하는 경우가 많습니다.
Bitmap 같은 변수를  Pointing하는 Object가 많으면, 포인트 객체가 0이 되기 전에는 가비지 콜렉션이 동작하지 않습니다.

예를들어
byte[] a = aByteArray;
 ....
byte[] b = a;  
...

이렇게 사용해 놓고 a = null; 해도 b=null; 이 될 때까지는 메모르 반환이 안됩니다.
가비지 콜렉터가 대단한게 아니고, 어떤 덩치있는 객체를 가르키는 변수가 0이 되면, 메모리를 반환해 주는 것입니다. 물론 그런 기능만 있는 것은 아니죠.
와.. 이러한 글은 처음보네요..

상세한 답변 정말 감사드립니다...

혹시 하나만 여쭈어봐도 될까요..?

boolean 변수같은 작은것은 괜찮고, bitmap과 같은 변수는 크기때문에 문제가 생길텐데요,

Layout과 같은 변수들 ( eg. private static LinearLayout = ~findViewById(~); )와 같은 변수도 정적으로 선언하기에는 너무 큰것인가요~?

물론 현재 App같은 경우 수시로 꺼졌다 켜지는 성향이고, static으로 선언할 Layout도 두어개 정도밖에 되지 않습니다만, 정적으로 선언해도 될지 걱정이 됩니다.

긴 답변 정말 감사합니다!
Layout 안에 뭐가 있는지에 따라 다르겠죠.
Static으로 선언하기 전에, onResume()에 값을 다시 세팅해 줄 때 화면이 이상한지 보는 것도 방법이죠.
기존 데이터를 SharedPreference에 보관했다가, onResume()에서 다시 세팅하는 것이 일반적으로 하는 방법입니다.
저는 가급적이면 특별한 화면이 아니라면, 세로나 가로로 고정해서 개발하는 것을 좋아합니다.
감사합니다~

일단은 선언해보고 이것저것 테스트를 진행해 봐야겠네요~ ㅎㅎ
...