728x90

코틀린에서 Retrofit2 라이브러리를 이용하여 서버 데이터를 가져오는 기능을 처리하는데 헷갈려서 정리를 좀 해둔다.


예제1)


먼저 PHP 코드에서 JSON 데이터를 만드는 방법

    $R = array(); // 결과 담을 변수 생성
    $result = $c->putDbArray($sql);
    while($row = $result->fetch_assoc()) {
        if($row['photo'] == NULL) {
            $row['photo'] = "";
        } else {
            $path = "./photos/".$row['photo'];
            if(!file_exists($path)) {
                $row['photo'] = "";
            }
        }
        array_push($R, $row);
    }
    header("Cache-Control: no-cache, must-revalidate");
    header("Content-type: application/json; charset=UTF-8");

    $status = "success";
    $result = array(
        'status' => $status,
        'message' => $R
    );
    echo json_encode($result);
 

while 문을 사용했다는 것은 $R 변수는 배열이라는 것을 명심하자.


서버에서 받은 데이터를 Retrofit 라이브러리에서 받아서 처리하기 위한 data class

@Parcelize
data class ContactData (
    // PersonData 정보를 담고 있는 객체 생성
    var idx: String,
    var userNM: String = "",
    var mobileNO: String = "",
    var officeNO: String = "",
    var photo: String = "", // 이미지 경로를 String으로 받기 위해서
    var isCheckBoxState: Boolean = false
): Parcelable
 

@Parcelize
class ContactDataResult (
    val status: String,
    val message: List<ContactData>
): Parcelable

interface IRetrofit {

    @FormUrlEncoded
    @POST(Value.Contacts)
    fun getContactDataResult(@Field("idx") idx: String): Call<ContactDataResult>
}
 


Retrofit 라이브러리 사용법

object RetroClient { // 싱글턴
    // 레트로핏 클라어언트 선언
    private var retrofitClient: Retrofit? = null
    var instance: IRetrofit? = null

    val gson = GsonBuilder().setLenient().create()

    // 레트로핏 클라어언트 가져오기
    fun getClient(baseUrl: String): Retrofit? {
        if (retrofitClient == null){
            retrofitClient = Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(Utils.createOkHttpClient())
                .build()
        }
        return retrofitClient
    }

    @JvmName("getInstance1")
    fun getInstance(): IRetrofit? {
        if (instance == null) {
            instance = getClient(Value.API_BASE_URL)?.create(IRetrofit::class.java)
        }
        return instance
    }

}
 

class Value : AppCompatActivity() {
    companion object{
        const val API_BASE_URL = "https://test.abc.com/androidSample/"
        const val Photo_URL = "https://test.abc.com/androidSample/photos/"

        const val Contacts = "getContactData.php"
    }
}
 

   private fun getServerData() {
        RetroClient.getInstance()?.getContactDataResult("1")?.enqueue(object :
            Callback<ContactDataResult> {
            override fun onResponse(call: Call<ContactDataResult>, response: Response<ContactDataResult>) {
                if (response.body()!!.status.contains("success")){
                    addressItemList.clear()
                    searchItemList.clear()

                    val contactData = response.body()!!.message
                    for (item in contactData){
                        addressItemList.add(item)
                        searchItemList.add(item)
                    }

                    runOnUiThread { // 갱신된 데이터 내역을 어댑터에 알려줌
                        mAdapter.notifyDataSetChanged()
                    }
                }
            }

            override fun onFailure(call: Call<ContactDataResult>, t: Throwable) {
                Log.e(TAG,"Retrofit response fail.")
            }

        })

    }
 



예제2)

PHP 코드 수정사항

echo json_encode(array('message'=>$R));


결과 형태

{"message":[{"idx":1,"userNM":"\uac1c\ubc1c\uc790","mobileNO":"01000010001","telNO":"0234560001","photo":"1.jpg"},
{"idx":2,"userNM":"\uc774\uc815\uc740","mobileNO":"01001230001","telNO":"","photo":"2.jpg"},
{"idx":3,"userNM":"\uae40\ud64d\uae38","mobileNO":"01001230002","telNO":"","photo":""},
{"idx":4,"userNM":"\ucd5c\uc2e0\ud615","mobileNO":"01001230003","telNO":"","photo":"4.jpg"}]}
 


코틀린 수정사항

@Parcelize
class ContactDataResult (
    val message: List<ContactData>
): Parcelable

// 수정사항 없음
@Parcelize
data class ContactData (
    // PersonData 정보를 담고 있는 객체 생성
    var idx: String,
    var userNM: String = "",
    var mobileNO: String = "",
    var officeNO: String = "",
    var photo: String = "", // 이미지 경로를 String으로 받기 위해서
    var isCheckBoxState: Boolean = false
): Parcelable
 


        RetroClient.getInstance()?.getContactDataResult("1")?.enqueue(object :
            Callback<ContactDataResult> {
            override fun onResponse(call: Call<ContactDataResult>, response: Response<ContactDataResult>) {
                if (response.isSuccessful){
                    addressItemList.clear()
                    searchItemList.clear()

                    val contactData = response.body()!!.message
                    for (item in contactData){
                        addressItemList.add(item)
                        searchItemList.add(item)
                    }

                    runOnUiThread { // 갱신된 데이터 내역을 어댑터에 알려줌
                        mAdapter.notifyDataSetChanged()
                    }
                }
            }

            override fun onFailure(call: Call<ContactDataResult>, t: Throwable) {
                Log.e(TAG,"Retrofit response fail.")
            }

        })
 


예제3)

PHP 코드 수정사항

echo json_encode($R);


JSON 결과==> 배열

[{"idx":1,"userNM":"\uac1c\ubc1c\uc790","mobileNO":"01000010001","telNO":"0234560001","photo":"1.jpg"},
 {"idx":2,"userNM":"\uc774\uc815\uc740","mobileNO":"01001230001","telNO":"","photo":"2.jpg"},
 {"idx":3,"userNM":"\uae40\ud64d\uae38","mobileNO":"01001230002","telNO":"","photo":""},
 {"idx":4,"userNM":"\ucd5c\uc2e0\ud615","mobileNO":"01001230003","telNO":"","photo":"4.jpg"},
 {"idx":5,"userNM":"\ud64d\uae38\ub3d9","mobileNO":"01000009880","telNO":"","photo":"5.jpg"}]
 


코틀린 수정사항


interface IRetrofit {
    @FormUrlEncoded
    @POST(Value.Contacts)
    fun getContactsList(@Field("idx") idx: String): Call<List<ContactData>>
}
 



        RetroClient.getInstance()?.getContactsList("1")?.enqueue(object :
            Callback<List<ContactData>> {
            override fun onResponse(call: Call<List<ContactData>>, response: Response<List<ContactData>>) {
                if (response.isSuccessful){
                    addressItemList.clear()
                    searchItemList.clear()

                    val contactData = response.body()!!
                    for (item in contactData){
                        addressItemList.add(item)
                        searchItemList.add(item)
                    }

                    runOnUiThread { // 갱신된 데이터 내역을 어댑터에 알려줌
                        mAdapter.notifyDataSetChanged()
                    }
                }
            }

            override fun onFailure(call: Call<List<ContactData>>, t: Throwable) {
                Log.e(TAG,"Retrofit response fail.")
            }

        })
 



예제4) JSON 파싱하기
PHP 코드 수정사항
echo json_encode(array('result'=>$R));

JSON 결과

{"result":[{"idx":1,"userNM":"\uac1c\ubc1c\uc790","mobileNO":"01000010001","telNO":"0234560001","photo":"1.jpg"},
           {"idx":2,"userNM":"\uc774\uc815\uc740","mobileNO":"01001230001","telNO":"","photo":"2.jpg"},
       {"idx":3,"userNM":"\uae40\ud64d\uae38","mobileNO":"01001230002","telNO":"","photo":""},
       {"idx":4,"userNM":"\ucd5c\uc2e0\ud615","mobileNO":"01001230003","telNO":"","photo":"4.jpg"},
       {"idx":5,"userNM":"\ud64d\uae38\ub3d9","mobileNO":"01000009880","telNO":"","photo":"5.jpg"}]}
 


코틀린 수정사항

interface IRetrofit {
    @FormUrlEncoded
    @POST(Value.Contacts)
    fun getContactsObject(@Field("idx") idx: String): Call<JsonObject>
} 

object ContactContract {
    const val _RESULTS = "result" // 서버 정보를 파싱하기 위한 변수 선언

    object Entry : BaseColumns {
        const val TABLE_NAME = "PBbook"
        const val _IDX = "idx" // 서버 테이블의 실제 필드명
        const val _NAME = "userNM"
        const val _MobileNO = "mobileNO"
        const val _telNO = "telNO"
        const val _Team = "Team"
        const val _Mission = "Mission"
        const val _Position = "Position"
        const val _Photo = "photo" // 이미지 필드
        const val _Status = "status"
    } // SQLite의 데이터 타입은 NULL, INTEGER, REAL, TEXT, BLOB 만 지원한다.
}
 

=== MainActivity.kt 파일에서 발췌 ===

    private fun getServerData() {
        RetroClient.getInstance()?.getContactsObject("1")?.enqueue(object :
            Callback<JsonObject> {
            override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
                if (response.isSuccessful){
                    addressItemList.clear()
                    searchItemList.clear()

                    val jsonObj = JSONObject(response.body().toString())
                    val person = jsonObj.getJSONArray(ContactContract._RESULTS)

                    for (i in 0 until person.length()) {
                        val c = person.getJSONObject(i)
                        val idx = c.getString(ContactContract.Entry._IDX)
                        val name = c.getString(ContactContract.Entry._NAME)
                        val mobileNO = c.getString(ContactContract.Entry._MobileNO)
                        val officeNO = c.getString(ContactContract.Entry._telNO)
                        val PhotoImage = c.getString(ContactContract.Entry._Photo)

                        Log.e(TAG,"name : " + name)

                        getAllDataList(idx, name, mobileNO, officeNO, PhotoImage, false)
                        selectDataList(idx, name, mobileNO, officeNO, PhotoImage, false)
                    }

                    runOnUiThread { // 갱신된 데이터 내역을 어댑터에 알려줌
                        mAdapter.notifyDataSetChanged()
                    }
                }
            }

            override fun onFailure(call: Call<JsonObject>, t: Throwable) {
                Log.e(TAG,"Retrofit response fail.")
            }

        })

    }
 
    // 아이템 전체 데이터 추가 메소드
    fun getAllDataList(uid: String, name: String, mobileNO: String, officeNO: String, photo_image: String, checkItem_flag: Boolean) {
        val item = ContactData(uid, name, mobileNO, officeNO, photo_image, checkItem_flag)
        addressItemList.add(item)
    }

    // 선택한 데이터 추가 메소드
    fun selectDataList(uid: String, name: String, mobileNO: String, officeNO: String, photo_image: String, checkItem_flag: Boolean) {
        val item = ContactData(uid, name, mobileNO, officeNO, photo_image, checkItem_flag)
        searchItemList.add(item)
    }
 




블로그 이미지

Link2Me

,