Merhabalar,


Bu yazıda Android'de bulunan Volley kütüphanesi ile bir API linkinden veri çekme işlemi üzerinde duracağız. Çektiğimiz verileri JSON Parse işleminden geçirerek ekranda göstereceğiz. Bu işlemleri Kotlin diliyle gerçekleştireceğiz. Ayrıca RecyclerView ve CardView kullanımına da ufak bir bakış atmış olacağız.


Örnek projeyi inceleyebilmeniz adına Github üzerinden paylaştım: Örnek proje linki


API için şu linki kullanacağız. Linke baktığımız zaman bize bir kullanıcı listesi dönmekte. Kullanıcıların ad, e-posta adresi ve telefon bilgilerini ekranda listeleyeceğiz.


İlk olarak Android Studio'da boş bir proje oluşturuyoruz.


Hemen ardından build.gradle dosyasına girerek gerekli kütüphaneleri ekliyoruz ve senkronizasyon (Sync) işlemi yapıyoruz:

implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.volley:volley:1.1.0'


activity_main.xml dosyasını açarak tüm ekranı kaplayacak şekilde RecyclerView'ı yerleştiriyoruz:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.activity.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvUsers"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"/>

</android.support.constraint.ConstraintLayout>


list_item.xml adında bir layout dosyası açarak RecyclerView'da görünecek elemanlar için özel (custom) ve basit bir tasarım oluşturuyoruz:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dp">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/root"
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:text="Leanne Graham"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tvName"
            android:textSize="20sp"
            android:drawableStart="@drawable/ic_name"
            android:drawablePadding="10dp"
            android:textColor="@color/colorPrimary"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toTopOf="parent"/>

        <TextView
            android:text="[email protected]"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tvEmail"
            android:textSize="15sp"
            android:drawableStart="@drawable/ic_email"
            android:drawablePadding="10dp"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toBottomOf="@+id/tvName"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"/>

        <TextView
            android:text="1-770-736-8031 x56442"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tvPhone"
            android:textSize="15sp"
            android:drawableStart="@drawable/ic_phone"
            android:drawablePadding="10dp"
            android:layout_marginTop="8dp"
            app:layout_constraintTop_toBottomOf="@+id/tvEmail"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"/>

    </android.support.constraint.ConstraintLayout>

</android.support.v7.widget.CardView>


Uygulamamızın Volley isteklerini karşılaması için VolleySingleton adında bir sınıf (class) oluşturuyoruz:

package com.yusufborucu.volleysample

import android.app.Application
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.Volley

class VolleySingleton : Application() {
    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    val requestQueue: RequestQueue? = null
        get() {
            if (field == null) {
                return Volley.newRequestQueue(applicationContext)
            }
            return field
        }

    fun <T> addToRequestQueue(request: Request<T>) {
        request.tag = TAG
        requestQueue?.add(request)
    }

    companion object {
        private val TAG = VolleySingleton::class.java.simpleName
        @get:Synchronized var instance: VolleySingleton? = null
            private set
    }
}


AndroidManifest.xml dosyasını açarak oluşturduğumuz VolleySingleton sınıfını ekliyoruz. Ayrıca veri çekme işlemi için internet gerekeceğinden internet iznini de dahil ediyoruz:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          package="com.yusufborucu.volleysample">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name=".VolleySingleton"
        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"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        <activity android:name=".ui.activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>


Projemizi düzenli bir şekilde ilerletmek adına ufak bir paket yapısı oluşturuyoruz:

com.yusufborucu.volleysample

-> model

-> ui

--> activity

--> adapter


Veri modelimizi belirtmek adına model paketimiz içerisinde User adında bir sınıf oluşturuyoruz:

package com.yusufborucu.volleysample.model

data class User(
    val name: String = "",
    val email: String = "",
    val phone: String = ""
)


Verileri RecyclerView içerisinde listelemek için ui/adapter paketimiz içerisinde UserAdapter adında bir sınıf oluşturuyoruz:

package com.yusufborucu.volleysample.ui.adapter

import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.yusufborucu.volleysample.R
import com.yusufborucu.volleysample.model.User
import kotlinx.android.synthetic.main.list_item.view.*

class UserAdapter(private val users : MutableList<User>) : RecyclerView.Adapter<UserAdapter.UserViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.list_item,parent,false)
        return UserViewHolder(v)
    }

    override fun getItemCount(): Int {
        return users.size
    }

    fun add(item:User, position:Int) {
        users.add(position, item)
        notifyItemInserted(position)
    }

    fun remove(item:User) {
        val position = users.indexOf(item)
        users.removeAt(position)
        notifyItemRemoved(position)
    }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = users[position]
        holder.itemView.tvName.text = user.name
        holder.itemView.tvEmail.text = user.email
        holder.itemView.tvPhone.text = user.phone
    }


    class UserViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
}


MainActivity sınıfımızı ui/activity paketimiz içerisine taşıyoruz. Ve MainActivity içerisinde API linkimize Volley ile isteği yapıp gelen veriyi JSON Parse işleminden geçirerek ekranda gösteriyoruz:

package com.yusufborucu.volleysample.ui.activity

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.widget.Toast
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.yusufborucu.volleysample.R
import com.yusufborucu.volleysample.model.User
import com.yusufborucu.volleysample.ui.adapter.UserAdapter
import org.json.JSONArray
import org.json.JSONException

class MainActivity : AppCompatActivity() {

    val users = mutableListOf<User>()
    var recylerView: RecyclerView? = null
    val URL = "https://jsonplaceholder.typicode.com/users"

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

        recylerView = findViewById(R.id.rvUsers)

        getUsers()
    }

    private fun getUsers() {
        val stringRequest = StringRequest(
            Request.Method.GET,
            URL,
            Response.Listener<String> { s ->
                try {
                    val array = JSONArray(s)
                    for (i in 0 until array.length()) {
                        val obj = array.getJSONObject(i)
                        users.add(
                            User(
                                obj["name"].toString(),
                                obj["email"].toString(),
                                obj["phone"].toString()
                            )
                        )
                    }
                    recylerView?.layoutManager = LinearLayoutManager(this)
                    recylerView?.adapter = UserAdapter(users)
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            },
            Response.ErrorListener { error ->
                Toast.makeText(this, error.message, Toast.LENGTH_SHORT).show()
            })

        val requestQueue = Volley.newRequestQueue(this)
        requestQueue.add<String>(stringRequest)
    }
}


Uygulamayı çalıştırdığımızda ekran görüntüsü aşağıdaki gibi olacaktır:


İyi çalışmalar.