개발일지

Android in A..Z - HTTP (Volley) 본문

Android (안드로이드)/HTTP

Android in A..Z - HTTP (Volley)

강태종 2021. 3. 16. 00:24

Volley

Volley는 2013년 구글에서 발표한 Android HTTP 라이브러리 입니다. (JavaScript에 Ajax와 매우 비슷한 구조이다.)

기존의 URLConnnection은 Request를 위한 기본 설정과 Thread를 만들어서 처리하는 보일러 코드가 필요하다는 단점이 있습니다.

Volley는 Callback으로 Response와 Error를 쉽게 처리할 수 있고, 비동기/동기 등 다양한 기능을 지원합니다.

Volley는 간단한 HTTP 통신에는 적합하지만. 모든 응답을 메모리에 유지하기 때문에 대용량의 전송은 적합하지 않습니다.


Dependency

dependencies {
    // Volley
    implementation 'com.android.volley:volley:1.2.0'
}

Volley 장점

  • 네트워크 요청의 자동 예약
  • 여러 개의 동시 네트워크 연결
  • 표준 HTTP 캐쉬 일관성을 갖춘 투명한 디스크 및 메모리 응답 캐싱
  • 요청 우선순위 지정 지원
  • 요청 취소 지원
  • 용이한 맞춤설정 (재시도, 백오프)

Volley Singleton

class VolleyHTTP private constructor(context: Context) {
    companion object {
        private var instance: VolleyHTTP? = null

        fun getInstance(context: Context): VolleyHTTP {
            return instance ?: synchronized(this) {
                instance ?: VolleyHTTP(context).also {
                    instance = it
                }
            }
        }
    }

    private val queue by lazy { Volley.newRequestQueue(context) }

    fun<T> request(req: Request<T>) {
        queue.add(req)
    }
}

StringRequest

String형식의 Response를 받을 때 사용합니다. 생성자는 Method, URL, Response.Listener, Response.ErrorListener를 필요로 합니다.

        val request = object : StringRequest(method, url,
                {
                    binding.resultTextView.text = it
                },
                {
                    binding.resultTextView.text = it.toString()
                }
        ) {
            override fun getHeaders(): MutableMap<String, String> {
                Log.d("PASS", "Call getHeaders($selectedContentType, $selectedMethod)")
                return HashMap<String, String>(super.getHeaders()).apply {
                    put("Content-Type", "application/x-www-form-urlencoded")
                }
            }

            override fun getParams(): MutableMap<String, String>? {
                Log.d("PASS", "Call getParams($selectedContentType, $selectedMethod)")
                return if (method == Method.POST) {
                    val parameter1 = binding.parameter1InputLayout.editText!!.text.toString()
                    val parameter2 = binding.parameter2InputLayout.editText!!.text.toString()

                    HashMap<String, String>().apply {
                        put("parameter1", parameter1)
                        put("parameter2", parameter2)
                    }
                } else {
                    super.getParams()
                }
            }
        }

        VolleyHTTP.getInstance(requireContext()).request(request)

추가적으로 Header나 Parameter, Body등 설정 사항이 있으면 object로 일회용 객체를 받아서 필요한 함수를 Override하면 됩니다.

Method가 GET일 때는 getBody(), getParamter() 등 HTTP표준에 어긋나는 함수들은 호출되지 않습니다.


JsonRequest

Json형식의 Response를 받을 때 사용합니다. 생성자로 Method, URL, JSONObject(Parameter), Respose.Listener, Response.ErrorListener를 필요로 합니다.

        val parameter1 = binding.parameter1InputLayout.editText!!.text.toString()
        val parameter2 = binding.parameter2InputLayout.editText!!.text.toString()
        val parameters = JSONObject(hashMapOf<Any?, Any?>("parameter1" to parameter1, "parameter2" to parameter2))

        val request = JsonObjectRequest(method, getURL(), parameters,
                {
                    binding.resultTextView.text = it.toString()
                },
                {
                    binding.resultTextView.text = it.toString()
                }
        )

        VolleyHTTP.getInstance(requireContext()).request(request)

추가적으로 Header나 Parameter, Body등 설정 사항이 있으면 object로 일회용 객체를 받아서 필요한 함수를 Override하면 됩니다.

Method가 GET일 때는 getBody(), getParamter() 등 HTTP표준에 어긋나는 함수들은 호출되지 않습니다.

Method가 POST일 때는 Content-Type이 application/json으로 설정됩니다.


RequestFuture

Volley는 기본적으로 비동기를 지원하지만 RequestFuture를 통해 동기로 처리할 수 있습니다.

RequestFuture의 Template를 Response받을 형식으로 설정하고, Request객체에 Response.Listener와 Response.ErrorListener를 RequestFuture로 대체합니다.

        val parameter1 = binding.parameter1InputLayout.editText!!.text.toString()
        val parameter2 = binding.parameter2InputLayout.editText!!.text.toString()
        val parameters = JSONObject(hashMapOf<Any?, Any?>("parameter1" to parameter1, "parameter2" to parameter2))

        val requestFuture = RequestFuture.newFuture<JSONObject>()

        val request = object : JsonObjectRequest(Method.POST, "${Server.PROTOCOL}://${Server.IP}:${Server.PORT}/application/json", parameters, requestFuture, requestFuture) {
            override fun getHeaders(): MutableMap<String, String> {
                return HashMap<String, String>(super.getHeaders()).apply {
                    put("Content-Type", "application/json")
                }
            }
        }.apply {
            // timeOutMs += timeOutMs * backoffMultiplier
            retryPolicy = DefaultRetryPolicy(1000, 2, 3.0F)
        }

        VolleyHTTP.getInstance(requireContext()).request(request)

        thread {
            val jsonObject = requestFuture.get()
            CoroutineScope(Dispatchers.Main).launch {
                binding.resultTextView.text = jsonObject.toString()
            }
        }

Policy

TimeOut, Retry, BackOff를 설정할 때 사용합니다. 생성자로 TimeOut, RetryCount, Backoff를 통해 DefaultRetryPolicy를 만들어서 설정한다.

        val request = object : JsonObjectRequest(Method.POST, "${Server.PROTOCOL}://${Server.IP}:${Server.PORT}/application/json", parameters, requestFuture, requestFuture) {
            override fun getHeaders(): MutableMap<String, String> {
                return HashMap<String, String>(super.getHeaders()).apply {
                    put("Content-Type", "application/json")
                }
            }
        }.apply {
            // timeOutMs += timeOutMs * backoffMultiplier
            retryPolicy = DefaultRetryPolicy(1000, 2, 3.0F)
        }

Git (예제코드)

github.com/KangTaeJong98/Example/tree/main/Android/HTTP

 

KangTaeJong98/Example

My Example Code. Contribute to KangTaeJong98/Example development by creating an account on GitHub.

github.com

 

'Android (안드로이드) > HTTP' 카테고리의 다른 글

Android in A..Z - HTTP (Retrofit2)  (0) 2021.03.16
Android in A..Z - HTTP (URLConnection)  (0) 2021.03.12
Android in A..Z - HTTP (개념)  (0) 2021.03.12
Comments