<테스크(Task)>

앱이 어떻게 동작할지 결정하는 데 사용된다.

프로세스는 독립적인 하나의 상자와 같아서 다른 프로세스와 정보를 공유할 수 없다.

즉 하나의 프로세스에서 다른 프로세스를 띄우려면 시스템의 도움이 필요함. 이 때 시스템에서 액티비티의 각종 정보를 저장해두기 위해 태스크를 만든다.

 

테스크의 흐름 관리 : 프로세스 실행 -> VM(Virtual Machine) 생성 -> 앱 실행

 

<매니패스트 파일에서 태스크 설정하기>

1. activity_main.xml을 다음과 같이 만들어준다.

 

2. MainActivity 코드를 작성한다.

<MainActivity.java>

package com.example.chapter4_5;

public class MainActivity extends AppCompatActivity {

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

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

 

버튼을 누르면 자기 자신을 호출한다.

 

실행 결과 : 버튼을 누를 때마다 앱 화면이 생성되는 효과가 보이고, [BACK] 버튼을 누를 시 화면이 생성된만큼 중첩되어있음을 확인할 수 있다.

 

3. Mainfest에 속성 추가

AndroidManifest.xml 화면에 MainActivity의 activity 태그 안에 launchmode = singleTop으로 속성을 추가해준다.

 

실행 결과 : 버튼을 여러번 눌러도 중첩되지 않는다. [BACK] 버튼을 누를 시 바로 앱이 종료되는 것을 확인할 수 있음.

 

이전에 작성한 플래그 글에도 singleTop에 대한 속성에 대해 작성한 내용이 있다.

https://sand-to-desert.tistory.com/75

 

singleTop, singleTask, singleInstance 등 다양한 속성 값이 존재한다.

 

<수명주기(Life Cycle)>

액티비티의 상태 정보가 변화하는 것. (=생명주기)

 

<액티비티의 대표적인 상태 정보>

  • 실행(Running) : 화면 상에 액티비티가 보임, 실행 상태.
  • 일시 정지(Paused) : 다른 액티비티가 위에 있어서 일부가 가려짐. 사용자에게 보이긴함. (ex.대화상자 때문에 가려짐)
  • 중지(Stopped) : 다른 액티비티에 의해 완전히 가려져 보이지 않음.

 

<상태 메서드(=콜백 메서드, Callback Method)>

액티비티가 처음 만들어진 후 없어질 때까지 상태가 변화하면서 각각에 해당하는 메서드가 자동으로 호출된다.

onCreate / onStart / onResume / onRestart / onPause / onStop / onDestroy

  • onCreate : 액티비티가 처음에 만들어졌을 때 호출됨
  • onStart : 액티비티가 화면에 보이기 바로 전에 호출됨
  • onResume : 액티비티가 사용자와 상호작용하기 바로 전에 호출됨

(새로운 액티비티가 만들어졌을 때 차례대로 onCreate -> onStart -> onResume 순으로 호출된다.)

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

(onRestart -> onStart 순으로 호출됨.)

  • onPause : 또 다른 액티비티를 시작하려고 할 때 호출됨 
  • onStop : 액티비티가 사용자에게 더 이상 보이지 않을 때 호출됨

(onPause, onStop 이 상태에서는 액티비티 강제종료 가능함)

  • onDestroy : 액티비티가 소멸되어 없어지기 전에 호출됨. 액티비티가 받는 마지막 호출

 

<액티비티 수명주기 확인하기>

1. 새 프로젝트를 만들고 액티비티를 추가한다.(MenuActivity)

2. activity XML을 아래와 같이 각각 배치한다.

 

3. <MainActivity.java>

package com.example.chapter4_6;

public class MainActivity extends AppCompatActivity {

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

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

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this,"onStart 호출됨", Toast.LENGTH_LONG).show();
        System.out.println("onStart 호출됨");
    }
    @Override
    protected void onStop() {/*생략*/}
    @Override
    protected void onResume() {/*생략*/}
    @Override
    protected void onPause() {/*생략*/}
    @Override
    protected void onDestroy() {/*생략*/}
}

 

onStart, onStop, onResume, onPause, onDestroy를 재정의한다. 그리고 안에 토스트 띄우는 코드랑 Logcat 출력 코드를 작성한다.

onCreate에도 마찬가지로 작성해준다.

 

button을 누르면 메뉴 화면을 띄우도록 작성한다.

 

4. <MenuActivity>

package com.example.chapter4_6;

public class MenuActivity extends AppCompatActivity {

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

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }
}

 

button을 누르면 메뉴가 사라지게 한다. (전달되는 값이 없기 때문에 onClick 안에 단순히 finish()만 존재한다.)

 

5. <실행결과>

 

위와 같이 메서드가 호출되는 순서를 알 수 있다. 메뉴화면을 닫을 때 onPause랑 onStrop 메서드가 호출됨.

onResume과 onPause는 화면이 보일 때와 보이지 않을 때 모두 호출된다.

 

-모르겠다-

onRestart는 재정의를 안 해줬기 때문에 당연히 나오지 않는구나~ 이해했지만 왜 onDestroy는 호출되었다는 문구가 뜨지 않는지 모르겠다. 책에서는 [BACK] 버튼을 눌러서 화면을 없앨 경우 호출된다고 적혀있는데.. 음

 

 

<SharedPreferences를 사용하여 간단한 데이터 저장, 복원하기>

위에 만들어둔 프로젝트에 이어서 한다.

 

mainActivity.java에 아래 코드들을 추가한다.

EditText nameInput;
nameInput = findViewById(R.id.nameInput);

 

saveState() 함수를 만든다. (저장) 이 메서드는 현재 입력상자에 입력된 데이터를 저장한다.

"pref" 문자열을 저장소의 이름으로 사용한다. 데이터 저장 후, commit 메서드까지 호출해야 실제로 저장된다.

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

 

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);
    }
}

 

onResume에 restoreState(),

onPause에 saveState() 함수를 추가해준다.

 @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this,"onResume 호출됨", Toast.LENGTH_LONG).show();
        System.out.println("onResume 호출됨");
        restoreState();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this,"onPause 호출됨", Toast.LENGTH_LONG).show();
        System.out.println("onPause 호출됨");
        saveState();
    }

 

<실행결과>

입력상자에 문자열 입력 후 버튼을 눌러서 메뉴를 띄운다. 돌아가기 버튼을 누르면 원래 화면이 나타나고, 입력상자에 입력했던 문자열이 그대로 나타난다.