๊ด€๋ฆฌ ๋ฉ”๋‰ด

JiYoung Dev ๐Ÿ–ฅ

[Android] HTTP ํ†ต์‹  - Volley (2023.07.18) ๋ณธ๋ฌธ

full stack/์•ˆ๋“œ๋กœ์ด๋“œ

[Android] HTTP ํ†ต์‹  - Volley (2023.07.18)

Shinjio 2023. 7. 18. 14:14

 

 

์ƒ์„ฑ๋œ Request ๊ฐ์ฒด๋Š” Request Queue์— ์ถ”๊ฐ€ 

 Request Queue : ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์“ฐ๋ ˆ๋“œ ์ƒ์„ฑํ•˜์—ฌ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„ ์‘๋‹ต ๋ฐ›์Œ

 

** ์•ˆ๋“œ๋กœ์ด๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ https:// ๋กœ ํ†ต์‹ ํ•จ

 

Volley ์‚ฌ์šฉ ์„ค์ •

 

https://developer.android.com/training/volley?hl=ko 

 

Volley ๊ฐœ์š”  |  Android ๊ฐœ๋ฐœ์ž  |  Android Developers

Volley ๊ฐœ์š” ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. Volley๋Š” Android ์•ฑ์˜ ๋„คํŠธ์›Œํ‚น์„ ๋” ์‰ฝ๊ณ , ๋ฌด์—‡๋ณด๋‹ค๋„ ๋” ๋น ๋ฅด๊ฒŒ ํ•˜๋Š” HTTP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. Volley๋Š”

developer.android.com

 

 

 

 

Volley ํ†ต์‹ 

 

** ์ฝ”๋“œ๊ฐ€ ์ž˜ ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ ์ž‘๋™์ด ๋˜์ง€ ์•Š์„ ๋•Œ

>> ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ญ์ œ ํ›„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด๋ณด๊ธฐ

>> ์‚ญ์ œ : ๋งˆ์šฐ์Šค ์™ผ์ชฝ ๋ฒ„ํŠผ ๊ธธ๊ฒŒ ๋ˆ„๋ฅธ ํ›„ App info > Uninstall

 

package com.sjy.ex20230718

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley

class MainActivity : AppCompatActivity() {

    lateinit var etUrl: EditText
    lateinit var btnUrl:Button
    lateinit var tvResult:TextView

    lateinit var reqQueue:RequestQueue

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

        //์ปดํฌ๋„ŒํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ
        etUrl = findViewById(R.id.etUrl)
        btnUrl = findViewById(R.id.btnUrl)
        tvResult = findViewById(R.id.tvResult)

        //reqQueue์ƒ์„ฑ
        //                      ํ˜„์žฌ activicty๋ฅผ context๋กœ
        reqQueue = Volley.newRequestQueue(this)

        //request์ƒ์„ฑ : ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์†Œ ์ž…๋ ฅ ํ›„ ์š”์ฒญ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ
        //๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜๋ฉด etUrl์— ์ž‘์„ฑ๋œ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์š”์ฒญ -> ์‘๋‹ต์˜ค๋Š” ๊ฐ’ ์ถœ๋ ฅ
        btnUrl.setOnClickListener {
            //etUrl์— ์ž‘์„ฑ๋œ ํ…์ŠคํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ -> ๋ฌธ์ž์—ด ๋ณ€ํ™˜
            val input = etUrl.text.toString()
            //์š”์ฒญ
            //request๊ฐ์ฒด ์ƒ์„ฑ
            //StringRequest : String ํƒ€์ž…์˜ ์‘๋‹ต๊ฐ’์„ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด
            //                  ๋‹จ์  : ๋Œ€์šฉ๋Ÿ‰ ๋„คํŠธ์›Œํฌ ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€
            val request = StringRequest(
                Request.Method.GET, //์š”์ฒญ๋ฉ”์„œ๋“œ(GET/POST)
                input, //์š”์ฒญ ์ฃผ์†Œ https://www.google.com
                {   //์š”์ฒญ๊ณผ ์‘๋‹ต์ด ์„ฑ๊ณตํ–ˆ์„ ๋•Œ (200)
                    //response -> ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•ด์ค€ ๊ฒฐ๊ณผ๊ฐ’
                    response ->
                    Log.d("response", response.toString())
                    tvResult.text = response
                },
                {   //ํ†ต์‹  ์‹คํŒจ
                    //error -> ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
                    error ->
                    Log.d("error", error.toString())
                    Toast.makeText(this, "error ๋ฐœ์ƒ", Toast.LENGTH_SHORT).show()
                }
            )

            //์ƒ์„ฑ๋œ request ๊ฐ์ฒด -> request Queue์— ์ถ”๊ฐ€
            // => ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์„œ๋ฒ„๋กœ ์š”์ฒญ, ์‘๋‹ต๋ฐ›๊ธฐ ๊ฐ€๋Šฅ
            reqQueue.add(request)
        }
    }
}

 

ํ†ต์‹  ๋ฐ์ดํ„ฐ ํ˜•์‹

 

 

CSV

๊ฐ€๋ณ์ง€๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑ(ํ†ต์‹ )ํ•˜๊ธฐ๊ฐ€ ์‰ฝ์ง€ ์•Š์Œ

 

XML

๋ฐ์ดํ„ฐ ํŒŒ์‹ฑํ•˜๊ธฐ์— ํŽธ๋ฆฌํ•จ. JSON ํ˜•์‹๋ณด๋‹ค ๋ฌด๊ฑฐ์›€

 

JSON

๋ฐ์ดํ„ฐ ํฌ๊ธฐ๋„ ๊ฐ€๋ณ๊ณ , ํŒŒ์‹ฑํ•˜๊ธฐ์—๋„ ํŽธ๋ฆฌํ•จ

 

 

๋‚ ์”จ ๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ

package com.sjy.ex20230718

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ListView
import android.widget.Toast
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import org.json.JSONObject

class WeatherActivity : AppCompatActivity() {

    lateinit var btnWeather:Button
    lateinit var listView: ListView

    lateinit var reqQueue:RequestQueue

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

        btnWeather = findViewById(R.id.btnWeather)
        listView = findViewById(R.id.lvWeather)

        //requestQueue ์ƒ์„ฑ
        reqQueue = Volley.newRequestQueue(this)

        //๋‚ ์”จ ๋ฐ์ดํ„ฐ ๊ฐ€์ง€๊ณ ์˜ค๊ณ  ์‹ถ์€ ๋„์‹œ ์ •์˜ -> ๋ฐฐ์—ด
        val cityList = arrayOf("Gwangju", "Seoul", "Jeju-do", "London", "New York")

        //WeatherVO ์ €์žฅ ๋ฐฐ์—ด
        val weatherList = ArrayList<WeatherVO>()

        //๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜๋ฉด OpenWeatherAPI๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ๋‚ ์”จ ๋ฐ์ดํ„ฐ ์š”์ฒญ
        //๋„์‹œ ์ด๋ฆ„์„ ๋ฐฐ์—ด์— ์ €์žฅ >> ๋“ค์–ด์žˆ๋Š” ๋„์‹œ์˜ ๊ฐœ์ˆ˜๋งŒํผ ์š”์ฒญ์ด ์ผ์–ด๋‚˜์•ผํ•จ
        btnWeather.setOnClickListener {

            //.. : ๋ ๊ฐ’ ํฌํ•จ
            //until : ๋ ๊ฐ’ ํฌํ•จ X
            //index ๋งˆ์ง€๋ง‰ ๊ฐ’์€ size-1์ด๋ฏ€๋กœ until์„ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
            for(i in 0 until  cityList.size){
                val request = StringRequest(
                    Request.Method.GET,
                    "https://api.openweathermap.org/data/2.5/weather?q=${cityList.get(i)}&appid=f074ee48da2e5d5517edac8b232392ec",
                    {
                            response ->
                        Log.d("response", response.toString())
                        val result = JSONObject(response)
                        val weather = result.getJSONArray("weather").get(0) as JSONObject
                        val state = weather.getString("main")
                        val main = result.getJSONObject("main")
                        val temp = main.getInt("temp")

                        //๋ฐ์ดํ„ฐ VO๋กœ ๋ฌถ๊ธฐ
                        //WeatherVO(cityList.get(i), state, temp-273)
                        //์ƒ์„ฑ๋œ VO๋Š” ๋ฐฐ์—ด์— ์ €์žฅ
                        weatherList.add(WeatherVO(cityList.get(i), state, temp-273))
                        //์–ด๋Œ‘ํ„ฐ ์ƒ์„ฑ (listView์— ๋ฟŒ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด)
                        //view์— ๊ฐ€์ง€๊ณ  ์˜จ ๋ฐ์ดํ„ฐ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•จ
                        val adapter = ArrayAdapter<WeatherVO>(applicationContext, android.R.layout.simple_list_item_1, weatherList)
                        //listView์— adaptor ์ ์šฉ
                        listView.adapter = adapter
                    },
                    {
                            error ->
                        Log.d("error", error.toString())
                        Toast.makeText(this, "error ๋ฐœ์ƒ", Toast.LENGTH_SHORT).show()
                    }
                )
                reqQueue.add(request)
            }
        }
    }
}

 

package com.sjy.ex20230718

//data : ์ผ๋ฐ˜ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ
//data class : POJO(Plain Old Java Object)
//              - ํด๋ž˜์Šค ๋‚ด์— ํ•„๋“œ, ์ƒ์„ฑ์ž, ๊ฒŒํ„ฐ, ์„ธํ„ฐ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์•„์ฃผ ๊ฐ€๋ฒผ์šด ํ˜•ํƒœ์˜ ์ž๋ฐ”
//  -> ํ•„๋“œ๋งŒ ์ž‘์„ฑ -> getter, setter ... ์ž๋™ ์ƒ์„ฑ
// ์กฐ๊ฑด
// 1) ์ตœ์†Œ ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ(ํ•„๋“œ)๊ฐ€ ์žˆ์–ด์•ผ ํ•จ
// 2) ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” val or var๋กœ ์„ ์–ธ
// 3) abstract, open(์ฝ”ํ‹€๋ฆฐ์—์„œ ๋ถ€๋ชจ ํด๋ž˜์Šค ์ง€์ •์‹œ ๋ถ™์—ฌ์ฃผ๋Š” ํ‚ค์›Œ๋“œ),
//      sealed(์ž์‹ํด๋ž˜์Šค๋ฅผ ์ œํ•œํ•˜๋Š” ํ‚ค์›Œ๋“œ),
//      inner(ํด๋ž˜์Šค ์•ˆ์— ํด๋ž˜์Šค(์ค‘์ฒฉ ํด๋ž˜์Šค) ์ง€์ • ํ‚ค์›Œ๋“œ) ์‚ฌ์šฉ ๋ถˆ๊ฐ€
// 4) ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์„ ์ˆ˜ ์—†์Œ (sealed ํด๋ž˜์Šค๋Š” ์ƒ์† ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ)
data class WeatherVO(var city:String, var state:String, var temp:Int)