<플래그>

같은 액티비티에 대해 인텐트를 두번 보내면 액티비티가 중복되는데 이를 막기 위해선 플래그를 사용하면 된다.

(먼저 액티비티는 스택 구조로 처리된다는 것을 알아두면 이해가 쉽다)

 

<대표적인 플래그>

  •  FLAG_ACTIVITY_SINGLE_TOP : 액티비티 A를 생성하는데 이미 생성된 액티비티 A가 있을 경우 그 액티비티를 재사용한다. (액티비티를 재사용하는 경우 onCreate 메서드가 호출되지 않기 때문에 onNewIntent 메서드를 재정의해서 인텐트 객체만 전달 받을 수 있다.)
  • FLAG_ACTIVITY_NO_HISTORY : 처음 이후에 실행된 액티비티는 액티비티 스택에 추가되지 않음. 시스템 [Back] 키를 누를 시 항상 맨 처음에 실행되었던 액티비티가 바로 보이게 됨. (ex. 알람 시스템. 알람이 여러번 발생해도 화면을 한번만 보여줌)
  • FLAG_ACTIVITY_CLEAR_TOP : 이 액티비티 위에 있는 다른 액티비티를 모두 종료 시키게 됨. 우선하는 액티비티를 만들 때 유용. (ex. 홈화면)

 

<부가 데이터>

번들 객체 안에 넣은 데이터. (키(Key)와 값(Value)을 쌍으로 넣음)

한 액티비티에서 다른 액티비티를 띄울 때 데이터를 전달해야 하는 경우, 부가 데이터(Extra Data)를 사용하는 방법을 권장한다고 함. (별도의 클래스를 만들어 처리해도 되지만 이 경우 다른 앱에서 화면을 띄울 경우 불가능함.)

 

인텐트 안에는 번들(Bundle) 객체가 들어 있는데, putExtra와 get@@@Extra 메서드로 데이터를 넣거나 빼낼 수 있다.

(@@@은 자료형) (ex. 문자열을 빼내는 메서드는 getStringExtra)

get@@@Extra에 데이터 값이 없을 경우 디폴트로 설정한 defaultValue 값이 반환된다.

 

기본 자료형뿐만 아니라 바이트 배열이나 Serializable 객체도 넣었다 뺄 수 있다.

 

<객체 데이터 전달>

객체 데이터는 바이트 배열로 변환하거나 Serializable 인터페이스를 구현하는 객체를 만들어 직렬화한 다음 전달해야 한다. 안드로이드의 경우 Serializable 대신 Parcelable 인터페이스를 권장함.

 

<Parcelable 인터페이스 사용하기>

describeContents 메서드, writeToParcel 메서드 구현, CREATOR 상수 생성을 해야한다.

  • describeContents : 직렬화하려는 객체의 유형을 구분함
  • writeToParcle : 객체가 가지고 있는 데이터를 Parcel 객체로 만들어줌
  • CREATOR : Parcel 객체로부터 데이터를 읽어 들여 객체를 생성함 (반드시 static final로 선언되어야 함)

 

<Parcelable 인터페이스 구현하기>

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

 

2. 새 액티비티를 하나 추가한다. (MenuActivity)

 

3. 새로운 클래스를 정의한다.

책에서는 app>java>org.techtown.sampleparcelable 폴더 우클릭 후 New>Java Class로 대화상자를 띄운 뒤, 입력상자에 SimpleData 입력 후 OK를 누르면 새로운 클래스 파일이 만들어진다고 한다.

 

<문제 상황>

근데 나한테는 org.techtown.sampleparcelable 폴더가 없는디. 무슨 폴더를 말하는 건지를 모르겠음.

그래서 깃허브에서 Do it! 안드로이드 앱 프로그래밍을 검색하자 개정7판 레포지토리가 있길래 들어가서 part2 폴더 > chapter4 > sampleparcelable 폴더를 탐색해보았더니 MainActivity.java랑 MenuActivity.java랑 같은 폴더에 들어있는 것을 보고 그렇게 하면 되겠다 하고 알게 됨.

나의 경우 com.example.chapter4_4에다 만들면 되는 것이었음.

 

4. SimpleData 클래스에 Parcelable 인터페이스 구현

<SimpleData.java>

package com.example.chapter4_4;

public class SimpleData implements Parcelable {
    int number;
    String message;

    public SimpleData(int num, String msg){
        number = num;
        message = msg;
    }

    public SimpleData(Parcel src){
    // Parcel 객체를 파라미터로 받게 되는 경우엔 readInt, readString 메서드 사용해서 데이터 읽어들임
        number = src.readInt();
        message = src.readString();
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){
    // SimpleData 객체를 만든다.
        public SimpleData createFromParcel(Parcel in){
            return new SimpleData(in);
        }
        public SimpleData[] newArray(int size){
            return new SimpleData[size];
        }
    };

    public int describeContents(){
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags){
    // SimpleData 객체 안에 들어있는 데이터를 Parcel 객체로 만드는 역할을 하는 메서드
        dest.writeInt(number);
        dest.writeString(message);
    }
}

 

CREATOR 객체 부분 코드는 사실 이해가 잘 안된다. 다른 부분도 이해가 100% 이해가는 건 아니지만.. 일단 넘어가자.

 

5. MainActivity 소스 코드 작성

<MainActivity.java>

package com.example.chapter4_4;

public class MainActivity extends AppCompatActivity {

    public static final int REQUEST_CODE_MENU = 101;
    public static final String KEY_SIMPLE_DATA = "data";

    @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(), MenuActivity.class);
                SimpleData data = new SimpleData(100, "Hello World!");
                intent.putExtra(KEY_SIMPLE_DATA, data);
                startActivityForResult(intent, REQUEST_CODE_MENU);
            }
        });
    }
}

 

onClick안의 코드를 보겠다.

Intent intent = new Intent(getApplicationContext(), MenuActivity.class);

MenuActivity.class를 파라미터로 넣는다.

SimpleData data = new SimpleData(100, "Hello World!");

100, "Hello World"가 메인 액티비티 -> 메뉴 액티비티로 전달하려는 데이터이다.

SimpleData 메서드를 사용하여 이 데이터를 Parcel 객체로 만든 뒤, SimpleData 객체 data로 선언한다.

intent.putExtra(KEY_SIMPLE_DATA, data);

인텐트 객체의 putExtra 메서드를 사용하여 SimpleData 객체를 부가 데이터로 추가.

 

6. activity_menu를 다음과 같이 만들어준다.

 

7. MenuActivity 소스 코드 작성

<MenuActivity.java>

package com.example.chapter4_4;

public class MenuActivity extends AppCompatActivity {

    TextView textView;
    public static final String KEY_SIMPLE_DATA = "data";

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

        textView = findViewById(R.id.textView);
        Button button = findViewById(R.id.button_back);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.putExtra("name", "amy");
                setResult(RESULT_OK, intent);
                finish();
            }
        });

        Intent intent = getIntent();
        processIntent(intent);
    }

    private void processIntent(Intent intent){
        if(intent!=null){
            Bundle bundle = intent.getExtras();
            SimpleData data = bundle.getParcelable(KEY_SIMPLE_DATA);
            if(intent!=null){
                textView.setText("전달받은 데이터\nNumber :"+data.number+"\nMessage : "+data.message);
            }
        }
    }
}

 

onClick 안의 코드.. 이해가 안간다. putExtra로 "name", "amy"라는 데이터를 넣었는데 예제 내용에서 이 데이터들이 보이지 않으니 왜 존재하는 건지 잘 모르겠음.

 

onCreate 안의 마지막 코드를 보자.

Intent intent = getIntent();
processIntent(intent);

메인 액티비티로부터 전달받은 인텐트 객체를 참조하기 위해 getIntent 메서드를 호출. 

processIntent함수에 intent를 전달했다.

 

processIntent 함수를 보자.

private void processIntent(Intent intent){
        if(intent!=null){
            Bundle bundle = intent.getExtras();
            SimpleData data = bundle.getParcelable(KEY_SIMPLE_DATA);
            if(intent!=null){
                textView.setText("전달받은 데이터\nNumber :"+data.number+"\nMessage : "+data.message);
            }
        }
    }

getExtras 메서드를 호출하면 Bundle 자료형의 객체가 반환된다. (번들 객체를 참조하지 않고 getStringExtra()를 써도 됨)

 

<실행화면>

"메뉴 화면 띄우기" 버튼을 누르면 전달받은 데이터가 나타나는 창이 뜬다.

 

 

이해가 잘 안되서 여기서 좀 시간을 끌어버렸다. 모르겠다고 오래 붙들고 있어봤자 아는거 아니니까 그냥 다음으로 넘기고 그냥 코드를 많이 작성하면서 익숙해지는 작업을 하자.