본문 바로가기
Android/Concepts

Intent를 이용한 Activity 간 데이터 전달

by JuHy_ 2020. 4. 3.

Intent는 기본적으로 컴포넌트 간 이동을 도와준다.

이 때 단순한 이동 뿐 아니라 Extra 데이터를 담을 수 있는 공간을 갖고 있어 데이터 전달이 가능하다.

저장된 데이터들은 (key, value) 형태로 저장되어 key 값을 통해 저장하고 불러올 수 있다.

 

Primitive Type Data

기본적인 자료형인 String, int, boolean 값의 extra 데이터는 각각의 함수를 지원해준다.

데이터를 저장할 때는 putExtra() 함수를 사용하고(매개변수에 따라 알아서 처리)

불러올 때는 불러올 데이터의 자료형에 따라 알맞은 get 함수를 사용하면 된다.

(Intent는 Activity 내에서 getIntent() 함수를 통해 불러올 수 있다)

 

실제로 Activity 간 String 데이터 전달을 구현해보자.

 

package com.juhy.myapplication;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

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 v) {
                Intent intent = new Intent(getApplicationContext(), NewActivity.class);
                startActivityForResult(intent, 101);
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == 101){
            String name = data.getStringExtra("name");
            Toast.makeText(getApplicationContext(), "Message from NewActivity: " + name, Toast.LENGTH_SHORT).show();
        }
    }
}

▲MainActivity

 

먼저 MainActivity에서는 버튼을 누르면 101번 코드와 함께 NewActivity로 이동하도록 해주었다.

그리고 NewActivity가 정상적으로 실행되고 종료되어 다시 MainActivity로 돌아올 때 extra 값을 전달받는다고 하면,

onActivityResult 함수에서에서 응답을 받아 처리하도록 해주어야 한다.

 

이 때,

requestCode는 activity 시작 시 보내주었던 코드번호

resultCode는 종료된 activity에서 보내준 코드번호

data는 activity가 종료되면서 넘어온 intent이다.

 

따라서 우리가 목표한 activity가 맞는지 조건문으로 확인해준 뒤에,

intent의 getStringExtra() 함수를 통해 데이터를 받을 수 있는데, 이 때 파라미터는 데이터를 불러오기 위한 key 값이다.

이 key 값은 종료되는 intent에서 데이터를 저장할 때 지정해 준 key값과 같아야 올바를 데이터를 불러올 수 있다.

 

마지막으로 불러온 데이터를 toast를 통해 띄워주었다.

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class NewActivity extends AppCompatActivity {

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

    @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("name", "mike");
        setResult(Activity.RESULT_OK, intent);
        finish();
    }
}

▲NewActivity

 

NewActivity에서는 뒤로가기 버튼을 눌렀을 때 intent를 생성하고,

생성한 intent에 putExtra() 함수를 통해 데이터를 넣어주었다.

이 때 첫번째 파라미터는 앞서 말한 데이터를 저장할 key값, 두번째는 저장할 value이다.

데이터를 저장했다면 setResult() 함수에 정상종료 신호(resultCode)와 intent를 넣어준다.

그 다음 finish()를 통해 Activity를 종료하면 된다.

 

실행해보면 NewActivity 종료 시 정상적으로 mike라는 데이터가 전달된 것을 볼 수 있다.

 

그렇다면 기본적인 자료형 외에 다른 클래스의 객체를 전달하고 싶다면 어떻게 할까?

 

 

Serializable

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.util.ArrayList;

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 v) {
                Intent intent = new Intent(getApplicationContext(), NewActivity.class);

                ArrayList<String> names = new ArrayList<String>();
                names.add("김철수");
                names.add("김민수");

                intent.putExtra("names", names);

                startActivity(intent);
            }
        });

    }

}

MainActivity에서 NewActivity로 ArrayList를 보내보자.

ArrayList 객체를 만든 뒤 데이터를 넣어주고 intent에 putExtra() 함수를 통해 넣어주자.

ArrayList는 primitive type이 아닌데 그럼 어떻게 불러와야 할까

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import java.util.ArrayList;

public class NewActivity extends AppCompatActivity {

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

        Intent intent = getIntent();
        ArrayList<String> names = (ArrayList<String>)intent.getSerializableExtra("names");
        Toast.makeText(getApplicationContext(), "length of received data: " + names.size(), Toast.LENGTH_SHORT).show();
    }

}

 

getIntent() 함수를 통해 intent를 불러온 뒤 getSerializableExtra() 함수를 사용하면 된다.

주의할 점은 ArrayList가 Serializable한 클래스이기 때문에 가능한 것이므로 모든 객체가 가능한 것은 아니다.

함수를 통해 불러왔다면 형변환을 통해 원래 자료형으로 변환해주면 된다.

 

하지만 Serializable을 통한 데이터 전달은 데이터의 크기가 크기 때문에 Parcelable의 사용을 권장한다.

 

 

Parcelable

이번에는 제공되는 클래스가 아닌 직접 만든 클래스를 전달해보자.

Parcelable을 사용하기 위해서는 직접 만든 클래스에 implements Parcelable을 붙여주어야 한다.

이 때 클래스가 Parcelable 한 조건을 만족하기 위해서는 정의해주어야 할 것이 여러 개 있다.

 

package com.juhy.myapplication;

import android.os.Parcel;
import android.os.Parcelable;

public class Customer implements Parcelable {

    int number;
    String name;

    public Customer(int number, String name) {
        this.number = number;
        this.name = name;
    }

    public Customer(Parcel src){
        number = src.readInt();
        name = src.readString();
    }

    // Parcel -> Customer
    public static final Creator<Customer> CREATOR = new Creator<Customer>() {
        @Override
        public Customer createFromParcel(Parcel in) {
            return new Customer(in);
        }

        @Override
        public Customer[] newArray(int size) {
            return new Customer[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }


    // Customer -> Parcel
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(number);
        dest.writeString(name);
    }

}

Parcelable은 기본적으로 일반 객체를 Parcel이라는 객체로 전환하여 전달하게 된다.

이를 위해 writeToParcel() 함수가 필요하며, 매개변수로 들어있는 dest에 멤버변수들을 write 시켜주면 된다.

 

그리고 전달받은 Parcel 객체를 다시 원래 객체로 돌려놓아야 한다.

이를 위해 CREATER가 필요하며, Parcel 객체가 생성자를 통해 들어왔을 때 데이터를 read 하도록 구현해준다.

 

Parcelable 클래스를 정의해주었다면 다음부터는 Serializable과 비슷하다.

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.util.ArrayList;

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 v) {
                Intent intent = new Intent(getApplicationContext(), NewActivity.class);

                Customer customer = new Customer(1, "김철수");

                intent.putExtra("customer", customer);

                startActivity(intent);
            }
        });

    }

}

우리가 만든 클래스로 객체를 생성해준 뒤 똑같이 putExtra()를 통해 intent에 넣고 액티비티를 실행해보자.

 

package com.juhy.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import java.util.ArrayList;

public class NewActivity extends AppCompatActivity {

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

        Intent intent = getIntent();
        Customer customer = intent.getParcelableExtra("customer");
        Toast.makeText(getApplicationContext(), "name of received data: " + customer.name, Toast.LENGTH_SHORT).show();
    }

}

마찬가지로 getIntent()를 통해 intent를 불러온 뒤 getParcelableExtra() 함수를 통해 불러와 객체에 넣어주면 된다.

Serializable과는 다르게 형변환을 해줄 필요는 없다.

 

 

Reference

[부스트코스]안드로이드 프로그래밍

https://www.edwith.org/boostcourse-android

'Android > Concepts' 카테고리의 다른 글

Service의 기본적인 사용법  (0) 2020.04.03
Activity Lifecycle(수명주기)란?  (0) 2020.04.03
Intent의 Flag 사용법  (0) 2020.04.02
Intent란?  (0) 2020.03.31
Activity란?  (0) 2020.03.31