Deperecated/Android_강의

안드로이드 - 객체 전달하기

누알라리 2020. 2. 18. 03:11
1. Parcelable

- Intent를 통해 객체를 전달할 때는 Parcelable 인터페이스를 구현한 객체만 가능하다.

- Parcelable 인터페이스는 전달받은 쪽에서 객체를 복원할 때 필요한 정보를 가진 부분을 의미한다.

 

- 안드로이드에서는 액티비티 - 액티비티간에 "객체 자체"를 전달할 수는 없고, "객체 안에 있는 값들을 전달"해서 받는 액티비티에서 "똑같은 객체를 새로 생성"해서 마치 객체가 전달 된 것 마냥 하는것이다.

 

-> 왜 이러는걸까?

1. 안드로이드의 4대 구성요소들은 모두 독립적인 실행단위이기 때문에.

2. 다른 어플리케이션이 갖고있는 4대 구성요소를 실행시키는것도 가능하기 때문에.

 

2. Parcelable 인터페이스를 구현한 클래스

1. class TestClass : Parcelable 인터페이스 구현

2. override fun writeToParcel(dest: Parcel?, flags: Int)

- 안드로이드에서 객체를 전달할 때는 객체가 전달되는게 아니라 Parcel 클래스 타입이 전달된다.
- 그래서 전달하고 싶은 데이터들을 Parcel 객체에 넣어주면 뽑아쓸 수 있다.

- 데이터를 넣은 순서와 나중에 빼는 순서가 같아야 한다.

- writeXXX()로 데이터를 넣는다.

4. CREATOR 변수 선언

- 나중에 data를 복원하는 쪽에서 안드로이드OS는 이 TestClass가 가지고 있는 CREATOR 라는 멤버를 갖고 메서드를 호출한다.

- 이 때 이 CREATOR 멤버는 Static으로 정의되어 있어야한다.

*Kotlin에서의 상수 
- Kotlin에서 상수를 사용할 땐 companion object 블록을 써서 한다.
- Kotlin에서 상수를 정의하는데 이를 안드로이드OS에서 쓸 경우 @JvmField를 붙여줘야한다.

- val CREATOR : Parcelable.Creator<TestClass> = object : Parcelable.Creator<TestClass>

5. CREATOR 변수에서 createFromParcel() 오버라이딩

- 객체를 복원하는 메서드.

- 매개변수에 Parcel 객체가 전달되기 때문에, 여기서 readXXX()로 데이터를 읽는다.

- 복원된 Parcel 객체를 반환 한다.

6. 만일 Parcel 객체가 하나가 아닌 배열로 들어왔을 땐 newArray() 를 오버라이딩해서 TestClass배열을 만들고 NULL로 채워준다.

 

package com.example.hyunndy_01

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

// 1. Parcelable 인터페이스 구현.
class TestClass : Parcelable{

    var data10 : Int = 0
    var data20:String? = null

    // 4.
    // 나중에 data를 복원하는 쪽에서 안드로이드OS는 이 TestClass가 가지고 있는 creater라는 멤버를 갖고 메서드를 호출한다. 이 때 이 Creater 멤버는 Static으로 정의되어 있어야한다.
    // Kotlin에서 상수를 사용할 땐 companion object를 써서 한다.
    companion object
    {
        // 5.
        // Kotlin에서 상수를 정의하는데 이를 안드로이드OS에서 쓸 경우 @JvmField를 붙여줘야한다.
        @JvmField

        // 이 이름은 반드시 CREATOR로 되있어야 한다.
        val CREATOR : Parcelable.Creator<TestClass> =  object : Parcelable.Creator<TestClass>
        {
            // 6. 객체를 복원하는 메서드.
            override fun createFromParcel(source: Parcel?): TestClass {
                val test = TestClass()

                // 객체 읽음
                test.data10 = source?.readInt()!!
                test.data20 = source?.readString()

                // 객체 복원
                return test
            }

            // 7.
            // 객체 하나가아니라 객체들의 배열이 전달되었을 경우..
            // 이 메서드가 먼저 불려서 배열이 만들어지고 각각의 멤버를 복원하기위해서 CreateFromParcel이 호출이 된다.
            override fun newArray(size: Int): Array<TestClass?> {

                // TestClass타입의 배열을 만드는데 그 안에 NULL값을 채워넣는다는것이다.
                return arrayOfNulls<TestClass>(size)
            }
        }
    }

    // 2.
    // 안드로이드에서 객체를 전달할 때는 객체가 전달되는게 아니라 Parcel 클래스 타입이 전달된다.
    // 그래서 전달하고 싶은 데이터들을 Parcel 객체에 넣어주면 뽑아쓸 수 있다.
    override fun writeToParcel(dest: Parcel?, flags: Int) {

        // 3.
        // 데이터를 넣은 순서와 나중에 빼는 순서가 같아야 한다.
        dest?.writeInt(data10)
        dest?.writeString(data20)

    }

    override fun describeContents(): Int {
        return 0
    }
}

 

3. Main Activity에서 Second Activity로 객체 전달.

1. Parcelable 인터페이스를 구현한 클래스 객체를 만든다.

2. 데이터를 세팅한다.

3. Intent를 생성하고 클래스 객체를 putExtra()로 넣은 후 보낸다.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        button2.setOnClickListener { view ->

            // 8. Parcelable 인터페이스를 구현한 클래스 객체를 만든다.
            var t1 = TestClass()
            t1.data10 = 100
            t1.data20 = "문자열2"

            var intent = Intent(this, SecondActivity::class.java)

            // 9. intent에 TestClass 객체를 넣는다. (정확히는 TestClass가 가진 값들)
            intent.putExtra("test", t1);
            startActivityForResult(intent, SECOND_ACTIVITY)
        }
    }

 

4. Second Activity에서 객체 복원.

1. Intent.getParcelableExtra<객체>("Main에서 전달받은 별명")으로 복원한다.

2. 전달받은 데이터로 막 한다.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)


        // 10. 메인 액티비티에서 Intent로 보낸 객체들의 값들을 받는다!
        var t1 = intent.getParcelableExtra<TestClass>("test")

        textView2.text = "t1.data1 : ${t1.data10}\n"
        textView2.append("t2.data2 : ${t1.data20}")
}

 

5. Second Activity에서도 Main Activity로 Intent를 통해 객체 전달하기.

1. Parcelable 인터페이스를 구현한 클래스 객체를 생성한다.

2. 데이터를 세팅하고, Intent를 생성하고 putExtra()로 넣은 후 setResult()로 resultCode와 Intent객체를 넣어서 보낸다.

        button10.setOnClickListener { view ->

            // 11. main으로도 보내기.
            var t2 = TestClass()
            t2.data10 = 200
            t2.data20 = "문자열2"

            var intent2 = Intent()
            intent2.putExtra("test2", t2)

            setResult(Activity.RESULT_OK, intent2)
            finish()
        }

 

6. Main Activity에서 데이터 복원하기.

1. OnActivityResult()의 매개변수로 Intent가 넘어오면, getParcelabeExtra()를 통해 데이터를 뽑는다.

    // 12. second 액티비티에서 보낸 데이터 받기.
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if(resultCode == Activity.RESULT_OK)
        {
            var t2 = data?.getParcelableExtra<TestClass>("test2")
            textView.text = "t2.data1 : ${t2?.data10}\n"
            textView.append("t2.data2 : ${t2?.data20}")
        }
    }