Merhaba arkadaşlar, Bugün dersimizde sizlere Square şirketi tarafından geliştirilen Retrofit kütüphanesinin kullanımı hakkında bilgi vereceğim. Retrofit açık kaynak kodlu REST İstemcisidir. Bu kütüphane biz geliştiricilerin işini gerçekten kolaylaştırıyor.
Sunucudan veri çekmek için kullandığımız diğer yöntemlere bakacak olursak:
AsyncTask yapısı ile yaptığımız isteklerde aşırı bir yavaş çalışma problemi ortaya çıkmıştı. Ayrıca çoklu asynchronous işlemlerinde , ön plandaki kontroller komplike bir hale dönüşmüştü.
Daha sonra ortaya Volley kütüphanesi çıktı o da bir network kütüphanesi olup , network bağlantılarını çok daha hızlı bir şekilde yapabilmemizi sağladığı gibi , bizi bir sürü kod yazmaktan kurtarmıştır. Ayrıca, Volley gösterilen URL adresine bağlanıp , orada sağlanan verileri bize sunuyor. Default olarak da Volley, sunucudan veri çekme gibi işlemleri asenkron olarak gerçekleştirebiliyor. Bunlardan dolayı da , AsyncTask yapısını kullanma gibi bir zorunluluk ortadan kalmış oluyordu.
Veri çekme ve network işlemleri , Retrofit kütüphanesi ile farklı bir boyut kazanmıştır.
Retrofit de ana kısmın url sini bütün API çağrıları için set edebilir , daha sonra static interfaceleri Java’nın annotation larını kullanarak oluşturabiliriz.
Sunucudan istek yapabilmek için , interface methodunu çağırmak yeterlidir ve sonucunda bize dönüş objesi dönmektedir.
AsyncTask, Volley ve Retrofit arasında genel bir karşılaştırma yapacak olursak da;
Volley ve Retrofit’in kullanımı AsyncTask dan daha kolaydır.
Volley ve Retrofit hız olarak AsyncTask a göre daha performanslıdır.
Retrofit ile JSON Parsing işlemleri otomatik olarak GSON ile gerçekleşmektedir.
Performans ile ilgili karşılaştırma verileri aşağıda yer almaktadır. Aşağıdaki verilere baktığımızda Retrofit ile istek yapıldığı zaman ; AsyncTask ve Volley e göre daha kısa bir sürede işlemin gerçekleştirildiğini göreceksiniz bu yüzden aralarında en hızlısı ve performanslısı Retrofit kütüphanesidir.
Retrofit kütüphanesinde kullandığımız Callback Interface yapısı ile otomatik olarak hataları ve cachelemeyi kontrol edebiliyoruz.
Şimdi gelelim bu dersimizin kodlamasına. Öncelikle retrofit kütüphanesini uygulamamızda kullanabilmemiz için build.gradle kısmına bunu ekliyoruz.
compile 'com.squareup.retrofit:retrofit:1.9.0'
sunucuya giden istekleri ya GET ile yada POST ile göndeririz bunu kontrol edebilmek içinde yine build.gradle kısmına aşağıdaki kodu ekliyoruz.
compile 'com.squareup.okhttp:okhttp:2.4.0'
Şimdi nasıl bir json verisi çekeceğimize bakalım :
Verileri bu adresten çekiyoruz. Tıkladığınız zaman aşağıdaki yapıyı göreceksiniz.
[ { "category": "Shrubs", "price": 15.99, "instructions": "Large double. Good grower, heavy bloomer. Early to mid-season, acid loving plants. Plant in moist well drained soil with pH of 4.0-5.5.", "photo": "california_snow.jpg", "name": "Azalea", "productId": 1 }, { "category": "Shrubs", "price": 33.99, "instructions": "Beautiful large royal purple flowers adorn attractive satiny green leaves that turn orange\\/red in cold weather. Grows to up to 18 feet, or prune annually to shorten.", "photo": "princess_flower.jpg", "name": "Tibouchina Semidecandra", "productId": 2 }, { "category": "Shrubs", "price": 12.99, "instructions": "Blooms in summer, 20-35 inches high. Fertilize regularly for best results. Full sun, drought tolerant.", "photo": "haight_ashbury.jpg", "name": "Hibiscus", "productId": 3 }, { "category": "Shrubs", "price": 5.99, "instructions": "Quick-growing, herbaceous, shrub reaching up to 30 inches in height, forming a rounded, dense bush.", "photo": "mona_lavender.jpg", "name": "Plectranthus", "productId": 4 }, { "category": "Shrubs", "price": 15.99, "instructions": "Slow growing, upright to spreading shrub. Oval, glossy, leaves and profuse winter to spring blooming flowers.", "photo": "camellia.jpg", "name": "Camellia Japonica", "productId": 5 }, { "category": "Shrubs", "price": 10.99, "instructions": "Thorny woody vine scrambles over other plants with their hooked thorns. Pest free.", "photo": "bougainvillea.jpg", "name": "Bougainvillea Spectabilis", "productId": 6 }, { "category": "Shrubs", "price": 22.99, "instructions": "Deep purple colored flowers bushy rounded growth habit to 3 feet tall. Plant in full sun. Water regularly.", "photo": "rosa_burgundy.jpg", "name": "Rosa Burgundy", "productId": 7 }, { "category": "Shrubs", "price": 22.99, "instructions": "Deep purple colored flowers bushy rounded growth habit to 3 feet tall. Plant in full sun. Water regularly.", "photo": "rosa_iceberg.jpg", "name": "Rosa Iceberg", "productId": 8 }, { "category": "Container Plants", "price": 45.99, "instructions": "They do not thrive indoors, where the light is too dim, and humidity too low, for them to grow properly.", "photo": "bonsai.jpg", "name": "Bonsai Tree", "productId": 9 }, { "category": "Container Plants", "price": 12.99, "instructions": "Blooms continuously from early spring to first frost. Full sun or part shade, moist well-drained soil.", "photo": "calibrachoa.jpg", "name": "Calibrachoa Noa", "productId": 10 }, { "category": "Container Plants", "price": 14.99, "instructions": "The flowers last about ten weeks. They have a waxy texture and reach a height of more than 20 inches.", "photo": "cymbidium.jpg", "name": "Cymbidium Aestivum", "productId": 11 }, { "category": "Container Plants", "price": 4.99, "instructions": "Creamy-white centers, medium green outer foliage with flattened outer foliage.", "photo": "flowering_kale.jpg", "name": "Brassica Oleracea", "productId": 12 }, { "category": "Container Plants", "price": 4.99, "instructions": "Compact mounds of colorful dainty flowers, good for window boxes. Fertile well drained soil.", "photo": "penny_orange_jumpup.jpg", "name": "Viola Penny Orange Jump Up", "productId": 13 }, { "category": "Container Plants", "price": 5.99, "instructions": "Cotula have very fragrant orange flowers that bloom in the middle of summer.", "photo": "pincushion.jpg", "name": "Cotula", "productId": 14 }, { "category": "Container Plants", "price": 4.99, "instructions": "Well drained neutral to slightly acid soil, bright light. Do not over-fertilize or these flowers will lose scent.", "photo": "pelargonium.jpg", "name": "Pelargonium Peltatum", "productId": 15 }, { "category": "Container Plants", "price": 3.99, "instructions": "Compact mounds of colorful dainty flowers, good for window boxes. Fertile well drained soil.", "photo": "pansy_blue_shades.jpg", "name": "Pansy Blue Shades", "productId": 16 }, { "category": "Container Plants", "price": 3.99, "instructions": "Compact mounds of colorful dainty flowers, good for window boxes. Fertile well drained soil.", "photo": "yellow_pansy.jpg", "name": "Pansy Yellow with Blotch", "productId": 17 }, { "category": "Container Plants", "price": 25.99, "instructions": "Choose the brightest windows in your house for your orchids, place on an humidity tray and spray regularly.", "photo": "phalaenopsis.jpg", "name": "Phalaenopsis Purple", "productId": 18 }, { "category": "Herbaceous Perennials", "price": 5.99, "instructions": "They thrive in fertile, fast draining, slightly alkaline (pH 6.75) soil. Avoid overwatering.", "photo": "dianthus.jpg", "name": "Dianthus", "productId": 19 }, { "category": "Herbaceous Perennials", "price": 9.99, "instructions": "Chrysanthemums respond to plenty of food and moisture, and prefer full sun.", "photo": "bronze_mums.jpg", "name": "Chrysanthemum", "productId": 20 }, { "category": "Herbaceous Perennials", "price": 7.99, "instructions": "Summer flowering, 12–18†high, likes full sun and well drained soil. Drought tolerant.", "photo": "armeria_allicaea.jpg", "name": "Armeria Alliacea", "productId": 21 }, { "category": "Herbaceous Perennials", "price": 6.99, "instructions": "Grows to 15 inches. The species is easy to grow from seeds or cuttings. This species prefers full sun.", "photo": "salvia.jpg", "name": "Salvia Splendens", "productId": 22 }, { "category": "Herbaceous Perennials", "price": 8.99, "instructions": "Easily grown, tolerant of drought and poor soil, flower and foliage improves with feeding. Full sun.", "photo": "agapanthus.jpg", "name": "Agapanthus", "productId": 23 }, { "category": "Herbaceous Perennials", "price": 5.99, "instructions": "These plants are very hardy, easy to grow, and increase readily. Average flower size is 3-4 inches in diameter.", "photo": "iris_siberica.jpg", "name": "Iris Sibirica", "productId": 24 }, { "category": "Herbaceous Perennials", "price": 9.99, "instructions": "Chrysanthemums grow best and produce the most flowers if they are planted in full sunshine.", "photo": "white_wedding.jpg", "name": "Chrysanthemum", "productId": 25 }, { "category": "Herbaceous Perennials", "price": 10.99, "instructions": "Grown primarily for its attractive silvergray foliage rather than its yellow flowers. Drought tolerant.", "photo": "dusty_miller.jpg", "name": "Senecio Cineraria", "productId": 26 }, { "category": "Cacti & Succulents", "price": 18.99, "instructions": "Add water until there is half inch of dry soil on the surface. Do not water again until the soil is completely dry.", "photo": "red_cactus.jpg", "name": "Red Cactus", "productId": 27 }, { "category": "Cacti & Succulents", "price": 30.99, "instructions": "Drought tolerant, well drained soil. Prefers full sun.", "photo": "aloe_vera.jpg", "name": "Aloe Vera", "productId": 28 }, { "category": "Cacti & Succulents", "price": 20.99, "instructions": "Easy to care for, requiring watering only when they’re dry. They like bright but indirect light.", "photo": "exotic_dancer.jpg", "name": "Schlumbergera", "productId": 29 }, { "category": "Cacti & Succulents", "price": 18.5, "instructions": "Locate it in a place where it is exposed to at least a few hours of direct sunlight.", "photo": "string_of_pearls.jpg", "name": "Senecio Rowleyanus", "productId": 30 }, { "category": "Cacti & Succulents", "price": 12.99, "instructions": "These plants blend in among the stones as a means of protection. Grazing animals would otherwise eat them.", "photo": "lithops.jpg", "name": "Lithops", "productId": 31 }, { "category": "Cacti & Succulents", "price": 55.99, "instructions": "The Mexican Fence Post will eventually reach 20 feet tall. Protect the growing tips with Styrofoam cups on the tops.", "photo": "mexican_fencepost_cactus.jpg", "name": "Pachycereus Marginatus", "productId": 32 }, { "category": "Cacti & Succulents", "price": 25.99, "instructions": "Growing as a large roughly spherical globe, it may eventually reach over a meter in height after many years.", "photo": "mexican_golden_barrel_cactus.jpg", "name": "Echinocactus Grusonii", "productId": 33 }, { "category": "Cacti & Succulents", "price": 16.99, "instructions": "The plants should be kept almost completely dry during the winter months, once a month should be fine.", "photo": "opuntia_cactus.jpg", "name": "Opuntia Falcata", "productId": 34 } ]
Şimdi ise yapmamız gereken bu linke tıklayarak karşımıza gelen ekrana json formatımızı yapıştırıyoruz. Yapıştırdıktan sonra belirli ayarları yapıyoruz aşağıdaki ekran görüntüsündeki gibi işaretli olan kısımlar seçili olmalıdır.
Source Type: JSON Annotation style: Gson
Ayarları yaptıktan sonra Preview tuşuna basıyoruz ve bize uygulamamızda kullanacağımız pojo model yapısını otomatik olarak oluşturmuş oluyoruz. buda aşağıdaki gibi olacaktır.
Yukarıda oluşturduğumuz yapıyı uygulamamıza ekleyelim.
RetrofitModel.java
package com.mobilhanem.retrofitexample; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class RetrofitModel { @SerializedName("category") @Expose public String category; @SerializedName("price") @Expose public Float price; @SerializedName("instructions") @Expose public String instructions; @SerializedName("photo") @Expose public String photo; @SerializedName("name") @Expose public String name; @SerializedName("productId") @Expose public Integer productId; }
Retrofit için kullanacağımız interface yapısıda aşağıdaki gibidir. Burada POST ile mi GET ile mi istek yapacağımıza annotation ları kullanarak karar veriyoruz. Bu derste GET ile istek yapacağım için o şekilde yapıyı oluşturdum. /servejson yazmamın nedeni ise base url den ( https://mobilhanem.com/test/retrofitJson.php ) sonra gelen parametreleri o şekilde ekleyerek sunucuya istekde bulunabiliyoruz.
RetrofitModel[ ] adını verdiğimiz bu yapı json array i döneceği için [ ] kullandık eğer dönen cevabımız json arrayı olarak dönmeyecekse aşağıdaki yapıda RetrofitModel yazmamız yeterli olacaktı.
RestInterfaceController.java ( Interface )
package com.mobilhanem.retrofitexample; import retrofit.Callback; import retrofit.http.GET; /** * Created by alperbeyler on 10/11/15. */ public interface RestInterfaceController { // GET yada POST mu olduğunu belirliyoruz. @GET("/servejson") void getJsonValues(Callback<RetrofitModel[]> response); }
MainActivity sınıfımız da aşağıdaki gibi olacaktır. Aşağıdaki yapıda Retrofit ile istekde bulunuyoruz oluşturulan Model den dönen cevaplarıda ListView de gösteriyoruz. Ayrıca ListView de hangi item e tıklandıysa yeni bir Activity e sunucudan gelen resmin adını gönderiyoruz ve o sayfada resmi gösteriyoruz. ListView i doldurmak için oluşturduğumuz Adapter sınıfını tekrar tekrar anlatmayacağım. Tek fark Adapter sınıfında Picasso kütüphanesi ile sunucudan dönen resimleri ListView de göstermek. Sizlere tavsiyem kaynak kodlarını indirip çalıştırmanızdır.
MainActivity.java
package com.mobilhanem.retrofitexample; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import retrofit.Callback; import retrofit.RestAdapter; import retrofit.RetrofitError; import retrofit.client.Response; import utils.Constants; public class MainActivity extends Activity { private Button start_button; private ListView listview; private RestAdapter restAdapter; private RestInterfaceController restInterface; private ProgressDialog progressDialog; private List<Items> list = new ArrayList<Items>(); private CustomAdapter customAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start_button = (Button)findViewById(R.id.startButton); listview = (ListView)findViewById(R.id.listview); // adapter ve servis oluşturma restAdapter = new RestAdapter.Builder() .setEndpoint(Constants.URL) .build(); restInterface = restAdapter.create(RestInterfaceController.class); start_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setMessage("Yükleniyor.."); progressDialog.setCancelable(false); progressDialog.show(); restInterface.getJsonValues(new Callback<RetrofitModel[]>() { // json array döneceği için modelimizi array tipinde belirledik @Override public void success(RetrofitModel[] model, Response response) { for (RetrofitModel modelValues : model) { Items items = new Items(); items.setName(modelValues.name); items.setCategory(modelValues.category); items.setInstructions(modelValues.instructions); items.setPhoto(modelValues.photo); items.setPrice(modelValues.price); items.setProductId(modelValues.productId); list.add(items); } progressDialog.cancel(); customAdapter = new CustomAdapter(getApplicationContext(),list); listview.setAdapter(customAdapter); } @Override public void failure(RetrofitError error) { String merror = error.getMessage(); Toast.makeText(getApplicationContext(),merror,Toast.LENGTH_LONG).show(); } }); } }); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(getApplicationContext(),DetailsActivity.class); // listview in hangi itemine tıklandıysa diğer sayfada ilgili resmi göstermek için sunucudan gelen resmin adını yolluyoruz. intent.putExtra("image_name",list.get(position).getPhoto()); startActivity(intent); } }); } }
Items.java
package com.mobilhanem.retrofitexample; import android.graphics.Bitmap; /** * Created by alperbeyler on 17/11/15. */ public class Items { private String name; private int productId; private String category; private double price; private Bitmap bitmap; private String instructions; private String photo; public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setProductId(int productId){ this.productId = productId; } public int getProductId(){ return this.productId; } public void setCategory(String category){ this.category = category; } public String getCategory(){ return this.category; } public void setPrice(double price){ this.price = price; } public double getPrice(){ return this.price; } public void setBitmap(Bitmap bitmap){ this.bitmap = bitmap; } public Bitmap getBitmap(){ return this.bitmap; } public void setInstructions(String instructions){ this.instructions = instructions; } public String getInstructions(){ return this.instructions; } public void setPhoto(String photo){ this.photo = photo; } public String getPhoto(){ return this.photo; } }
Yukarıda bahsetmiş olduğum Listview için yarattığımız Adapter sınıfıda aşağıdadır.
CustomAdapter.java
package com.mobilhanem.retrofitexample; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import java.util.ArrayList; import java.util.List; import utils.Constants; /** * Created by alperbeyler on 17/11/15. */ public class CustomAdapter extends ArrayAdapter<Items> { private Context context; private ViewHolder viewHolder; private List<Items> arrayList = new ArrayList<Items>(); public CustomAdapter(Context context, List<Items> list_items) { super(context, R.layout.item_layout, list_items); this.context = context; this.arrayList = list_items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if(view == null){ LayoutInflater layoutInflater = LayoutInflater.from(getContext()); view = layoutInflater.inflate(R.layout.item_layout, parent,false); viewHolder = new ViewHolder(); viewHolder.txt_name = (TextView)view.findViewById(R.id.name); viewHolder.image = (ImageView)view.findViewById(R.id.img); viewHolder.category = (TextView)view.findViewById(R.id.category); viewHolder.price = (TextView)view.findViewById(R.id.price); view.setTag(viewHolder); }else{ viewHolder = (ViewHolder) view.getTag(); } //Items items_info = getItem(position); viewHolder.txt_name.setText("Name: " + "" + arrayList.get(position).getName()); // name değerini textview e atıyoruz viewHolder.category.setText("Category: " + "" + arrayList.get(position).getCategory()); // category değerini textview e atıyoruz viewHolder.price.setText("Price: " + "" + String.valueOf(arrayList.get(position).getPrice()).toString()); // price değerini textview e atıyoruz // picasso kütüphanesi kullanarak ilgili resmi aldıktan sonra imageview e set ettik Picasso.with(getContext()).load(Constants.URL_IMAGES+arrayList.get(position).getPhoto()).resize(300,300).into(viewHolder.image); return view; } private static class ViewHolder{ TextView txt_name; ImageView image; TextView category; TextView price; } }
Evet arkadaşlar işte bu kadar kolay ve hızlı bir şekilde sunucudan gelen verileri çekmiş olduk. Dediğim gibi kaynak kodlarını indirirseniz önemli yerlerine yorum olarak açıklamalarda ekledim ,bu kütüphanenin çalışma mantığını daha iyi anlayacaksınız. Json Parsing işlemini de otomatik olarak kendi içinde halletmeside bu kütüphanenin önemli özelliklerinden biridir. Umarım faydalı bir ders olmuştur , Retrofit kütüphanesi ile ilgili izlenimlerinizi söylerseniz hem kullanımı açısından hem de bilgi birikimi açısından önemli olacaktır.
Tüm Android Ders, Proje ve Kaynak Kodlar için tıklayınız.
Ders hakkında soru ve önerilerinizi çekinmeden yorum bırakabilirsiniz. Bol Android’li günler sizin olsun 🙂
Sizlerden ricamız facebook.com/mobilhanem sayfamızı beğenmenizdir. Diğer dersimde görüşmek üzere kendinize iyi bakın..