ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Volley를 이용한 HTTP 통신
    Android/Network 2019. 7. 23. 00:31

    안드로이드가 배구..?

    HttpURLConnection은 통신이 많은 소스들과 불편함을 겪어야 했지만 이번 시간에는 Volley를 사용하여서 좀더 쾌적한 HTTP 통신을 해보로독 하겠다.

     

    Volley는 2013년 Google I/O 에서 발표한 라이브러리이다.

    http 통신을 위한 다양한 기능을 제공해주고 1.0.0 버전에서는 내부적으로 apache http 라이브러리를 이용 했었지만 1.1.1 버전에서는 apache http 종속성이 제거된 라이브러리이다.

     

    간단하게 사용할 것을 소개 하자면 아래와 같다.

     

    RequestQueue : 서버 요청자
    StringRequest : 문자열을 결과로 받아 오는 정보

    ImageRequest : 이미지를 결과로 받아 오는 정보
    JsonObjectRequest : JSONObject 를 결과로 받아 오는 정보
    JsonArrayRequest : JSONArray 를 결과로 받아 오는 정보


    1. AndroidMenifest.xml 과 Gradle Dependency 설정하기

     

    HTTP 통신에 있어서 가장 중요한 것은 Internet이다

    까먹지 않고 펄미션을 등록해주도록 하자

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.example.myapplication">
    
        <uses-permission android:name="android.permission.INTERNET"/>
    
        <application
                android:allowBackup="true"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    Gradle Dependency는 리스트 출력을 위한 recyclerView를 사용하고 이미지는 이전과 같이 Glide를 사용할 것이다.

    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.github.bumptech.glide:glide:3.8.0'

    2. UI와 Item 작성하기

     

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">
    
        <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/main_recycler"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    photo_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
        <TextView
                android:id="@+id/photo_tittle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintTop_toTopOf="parent"/>
    
        <ImageView
                android:id="@+id/photo_image"
                android:layout_width="240dp"
                android:layout_height="200dp"
                app:layout_constraintTop_toBottomOf="@id/album_tittle"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    3. Recycler 구조 만들기

     

    Photo.kt

    나중에 HTTP 통신을 통해 데이터를 받아와 저장시킬 데이터 클래스

    data class Photo(
        val albumId: Int,
        val id: Int,
        val title: String,
        val url: String,
        val thumbnailUrl: String
    )

    PhotoAdapter.kt

    Recycler에 필요한 어뎁터 역할 ViewHolder는 InnerClass로 구현

    class PhotoAdapter(
        private val context: Context
    ) : ListAdapter<Photo, PhotoViewHolder>(DIFF_CALL) {
    
        companion object {
            val DIFF_CALL = object : DiffUtil.ItemCallback<Photo>() {
                override fun areItemsTheSame(oldItem: Photo, newItem: Photo): Boolean {
                    return oldItem.id == newItem.id
                }
    
                override fun areContentsTheSame(oldItem: Photo, newItem: Photo): Boolean {
                    return oldItem == newItem
                }
            }
        }
    
        override fun onBindViewHolder(holder: PhotoViewHolder, position: Int) {
            position.log()
            with(getItem(position)) {
                holder.tvTitle.text = title
                Glide.with(context)
                    .load(url)
                    .into(holder.ivImage)
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoViewHolder {
            return PhotoViewHolder(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.photo_item,
                    parent,
                    false
                )
            )
        }
    
        inner class PhotoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val tvTitle: TextView = itemView.photo_tittle
            val ivImage: ImageView = itemView.photo_image
        }
    
    }

    4. 본격적인 Volley을 통한 HTTP 통신 구조 만들기

    class VolleyClient(private val context: Context) {
    
        fun execute(requestListener: Response.Listener<JSONArray>,
        		errorListener: Response.ErrorListener) {
    
            // Request를 담을 Queue를 생성해줍니다.
            val queue = Volley.newRequestQueue(context)
    
            // 요청할 Request 정보를 담아줍니다.
            // 현재 데이터가 JsonArray 일 경우 JsonArrayRequest
            // 데이터가 JsonObject 일 경우 JsonObjectRequest
            // 로 알맞게 사용하면 된다.
            val request = JsonArrayRequest(
                Request.Method.GET,
                "http://192.168.0.2:3000/photos",
                null,
                requestListener,
                errorListener
            )
    		
            // 큐에 추가시켜 줍니다.
            queue.add(request)
    
        }
    
    }

    일단 이전 HttpUrlConnection과 비교 하면 Client 부분이 매우 간단합니다. Listener는 구현만 하면 되기 때문이구요

     

    그리고 큐?가 보이네요 Volley는 Requets를 Queue에 담아서 하나하나 요청을 보내는 작업을 합니다.

    그래서 큐 안에 넣어넣고 처리를 하는 거죠


    5. 마무리 Activity 작업

    class MainActivity : AppCompatActivity() {
    
        private lateinit var photoAdapter: PhotoAdapter
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            photoAdapter = PhotoAdapter(this)
            main_recycler.adapter = photoAdapter
            main_recycler.layoutManager = LinearLayoutManager(this)
            main_recycler.setHasFixedSize(true)
    
            VolleyClient(this).execute(
                requestListener = Response.Listener {
                    val photoList = Gson().fromJson<Array<Photo>>(it.toString(), Array<Photo>::class.java)
                    photoAdapter.submitList(photoList.toList())
                },
                errorListener = Response.ErrorListener {
                    Log.e("dong", "에러남")
                }
            )
        }
        
    }

    뒤에 설명할 Retrofit외에도 사용되는 Http 통신 라이브러리 입니다.

    확실히 HttpUrlConnection 보다는 사용하기도 쉽고 구현도 쉽기 때문이죠!

     

    댓글

Designed by Tistory.