Android Butter Knife Kullanımı

Merhaba arkadaşlar bu dersimizde sizlere ; son zamanlarda Android dünyasına yönelik geliştirmiş olduğu kütüphaneler ile ( Picasso, ActionBarSherlock, Retrofit vb. ) öne çıkan Square şirketinin ortaya çıkardığı Butter Knife isimli kütüphanenin nasıl kullanılacağını anlatacağım.

Butter Knife bir View Injector kütüphanesidir bu kütüphane sayesinde ön yüzde kullandığımız android bileşenlerini annotation’lar kullanarak uygulamamızda direkt olarak erişebilmemizi sağlıyor. Aynı zamanda uygulamalarımızda kullandığımız view lere, verdiğimiz tıklanma event lerini de, projemize daha pratik bir şekilde eklememize yardımcı oluyor. Bu kütüphanenin temel amacı kod tekrarını azaltmak ve yazılımcılara daha hızlı ve daha pratik çözümler sunmaktır.

Butter Knife kütühanesini Android Studio da kullanabilmemiz için AndroidManifest.xml dosyamızda build.gradle kısmına aşağıdaki kod bloğunu yapıştırıyoruz.

compile 'com.jakewharton:butterknife:7.0.1'

* Bu kütüphane bizlere ; her bir view tanımladıktan sonra o view lere erişmek için kullandığımız findViewById methodu yerine daha kısa bir çözüm yolu sunuyor

*  Oluşturulan çoklu view leri listelerde yada array lerde gruplandırabildiğimiz gibi, tek bir komut ile view leri şekillendirebilmemizi sağlıyor. ( ACTION, SETTERS vb. interface yapıları kullanarak )

*  Kod tekrarı yapmaktan kurtuluyoruz.

3 tane button yarattık ve buttonlara ayrı ayrı tıklandığı zaman Toast mesajı ekrana bastırmak istiyoruz diyelim: Butter Knife kütüphanesi olmadan bu işlemi nasıl gerçekleştiriyoruz : Aşağıdaki kod bloğunda gördüğünüz gibi tanımladığımız üç butona da erişmek için findViewById methodunu kullandık ve setOnClickListener eventini her butona ayrı ayrı verirken de uzun bir şekilde kodlamamızı yaptık.

MainActivity.java

package com.mobilhanem.butterknifeexample;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    private Button buttonFirst, buttonSecond, buttonThird;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buttonFirst = (Button)findViewById(R.id.buttonFirst);
        buttonSecond = (Button)findViewById(R.id.buttonSecond);
        buttonThird = (Button)findViewById(R.id.buttonThird);

        buttonFirst.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(getApplicationContext(),"İlk buton tıklandı",Toast.LENGTH_SHORT).show();
            }
        });

        buttonSecond.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(getApplicationContext(),"İkinci buton tıklandı",Toast.LENGTH_SHORT).show();
            }
        });

        buttonThird.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(getApplicationContext(),"Üçüncü buton tıklandı",Toast.LENGTH_SHORT).show();
            }
        });


    }
}

Şimdi ise Butter Knife kütüphanesi kullanarak yukarıdaki işlemleri nasıl yaptığımıza bakalım : aşağıdaki kodlama yapısına baktığımız zaman findViewById lerin yerine @Bind ile buttonları tanımladığımızı göreceksiniz. Ayrıca yukarıda kullandığımız setOnClickListener methodu yerine de @OnClick ile bu işlemi yaptığımızı göreceksiniz. İşte bu şekilde hem kod fazlalığını azaltmış olduk hemde daha basit bir hale getirdik. İki örnek kodlama da karşınızda sizde inceleyip hangisinin daha kolay olduğunu görebilirsiniz.

MainActivity.java

package com.mobilhanem.butterknifeexample;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;

import butterknife.ButterKnife;
import butterknife.Bind;
import butterknife.OnClick;


public class MainActivity extends Activity {

    // findViewById yerine kullandık
    @Bind(R.id.buttonFirst) Button first_button;
    @Bind(R.id.buttonSecond) Button second_button;
    @Bind(R.id.buttonThird) Button third_button;

    @OnClick(R.id.buttonFirst) void showToastFirst(){   // tıklanma eventini kısaltarak kod fazlalığını azalttık

        Toast.makeText(getApplicationContext(),"İlk buton tıklandı",Toast.LENGTH_LONG).show();
    }

    @OnClick(R.id.buttonSecond) void showToastSecond(){

        Toast.makeText(getApplicationContext(),"İkinci buton tıklandı",Toast.LENGTH_LONG).show();
    }

    @OnClick(R.id.buttonThird) void showToastThird(){

        Toast.makeText(getApplicationContext(),"Üçüncü buton tıklandı",Toast.LENGTH_LONG).show();
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.bind(this);
    }
}

Uygulamamızın görsel kısmı da aşağıdadır.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <LinearLayout
        android:layout_centerVertical="true"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <Button
            android:text="Butter Knife First"
            android:id="@+id/buttonFirst"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            />

        <Button
            android:text="Button Knife Second"
            android:id="@+id/buttonSecond"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

        <Button
            android:text="Button Knife Third"
            android:id="@+id/buttonThird"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />



    </LinearLayout>


</RelativeLayout>

Ayrıca, String , Color, Drawable gibi android kaynaklarını da aynı şekilde oluşturarak kod tekrarları yapmaktan kurtulmuş oluyoruz. Örnek kodlama yapısı aşağıdadır:

@BindString(R.string.title) String name; // string yapısı için 
@BindDrawable(R.drawable.graphic) Drawable graphic; // drawable yapısı için
@BindColor(R.color.red) int red; // color yapısı için

Peki bu yapı nasıl çalışıyor şimdi ise ona bakalım; derleme işleminin aşamalarından birisi olan Annotation Processing sayesinde bu işlemler hızlıca gerçekleşir. Uygulamalarımızın runtime sırasında daha annotation lar oluşmamıştır. Uygulamayı derlediğimiz zaman Annotation Processor yapısı ortaya çıkarak projedeki tüm  .java uzantılı sınıfları tarayarak annotationları bularak kod satırına çevirir. Butter Knife kütüphanesinin yaptığı işte budur; annotation ları bularak ide tarafından okunabilir kodlara çevirir. Sizde Butter Knife gibi bir View Injector kütüphanesi oluşturabilirsiniz bunun için de kendi Annotation Processor sınıfını oluşturmanız gerekmektedir.

Bu dersimiz için hazırlamış olduğum uygulamayı indirip kaynak kodlarını incelerseniz sizin için daha faydalı olacaktır. Comment içine aldığım methodlarıda açarak hangi kodun ne için yazıldığını anlayabilirsiniz.

ButterKnife.Action ve ButterKnife.Setter methodlarınıda uygulamada kullandım. Action methodunda ilk butona tıklandığı anda çalışması gereken kod bloğu yer almaktadır. Kısaca anlatacak olursam; uygulamadaki birinci butona tıkladığımız anda Butter Knife kütüphanesinin Action methodu devreye giriyor ve çalışıyor bu method Button tipinde android bileşenlerini barındıran bir Liste ile birlikte methodun kendi ismini alıyor. Daha sonra aldığımız Liste de yer alan butonların index lerine göre renklerini değiştiriyor. Zaten kaynak kodlarını incelersek yorum şeklinde açıklamalar yaptığımı göreceksiniz.

Button tipinde android bileşenlerini barındıran bir List yapısı oluşturmak için bunu yapıyoruz: ( Aşağıda gördüğünüz gibi ; bu uygulamada 3 adet buton kullandığımız için o butonların id lerini tanımladık ve buttons_list adını verdiğimiz List yapısını oluşturduk. )

@Bind({R.id.buttonFirst,R.id.buttonSecond,R.id.buttonThird}) List<Button> buttons_list;

Oluşturduğumuz butonların renklerini değiştirmek için de yukarıda bahsetmiş olduğum ButterKnife.Action yapısından faydalandık. ( Aşağıda gördüğünüz gibi changeColor adını verdiğimiz Action yapısını oluşturduk ve butonlara renklendirme işlemini tamamladık. )

public ButterKnife.Action<Button> changeColor = new ButterKnife.Action<Button>() {
        @Override
        public void apply(Button button, int i) {

            buttons_list.get(0).setBackgroundColor(Color.BLUE); // birinci buton mavi renk alıyor
            buttons_list.get(1).setBackgroundColor(Color.RED);  // ikinci buton kırmızı renk alıyor
            buttons_list.get(2).setBackgroundColor(Color.GRAY); // üçüncü buton gri renk alıyor

           // button.setBackgroundColor(Color.BLUE); // bütün butonların rengini mavi yapar.

        }
    };

Yukarıda yazmış olduğumuz Action methodunu çalıştırmak için de birinci butonumuzu yine Butter Knife kütüphanesine bağlı olan apply komutu ile tetikledik.

@OnClick(R.id.buttonFirst) void clickEvent(){   // tıklanma eventini kısaltarak kod fazlalığını azalttık
        
// List yapımızı ve Action komutunu oluştururken vermiş olduğumuz fonksiyon ismini verdik
        ButterKnife.apply(buttons_list,changeColor);
    }

Action ve Setter methodlarının da bulunduğu kodlarımızın bütününe bakacak olursak :

MainActivity.java

package com.mobilhanem.butterknifeexample;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.List;

import butterknife.ButterKnife;
import butterknife.Bind;
import butterknife.OnClick;


public class MainActivity extends Activity {

    // findViewById yerine kullandık
    @Bind(R.id.buttonFirst) Button first_button;
    @Bind(R.id.buttonSecond) Button second_button;
    @Bind(R.id.buttonThird) Button third_button;

    @Bind({R.id.buttonFirst,R.id.buttonSecond,R.id.buttonThird}) List<Button> buttons_list;

    public ButterKnife.Action<Button> changeColor = new ButterKnife.Action<Button>() {
        @Override
        public void apply(Button button, int i) {

            buttons_list.get(0).setBackgroundColor(Color.BLUE); // birinci buton mavi renk alıyor
            buttons_list.get(1).setBackgroundColor(Color.RED);  // ikinci buton kırmızı renk alıyor
            buttons_list.get(2).setBackgroundColor(Color.GRAY); // üçüncü buton gri renk alıyor

           // button.setBackgroundColor(Color.BLUE); // bütün butonların rengini mavi yapar.

        }
    };

    public ButterKnife.Setter<View,Boolean> disableButtons = new ButterKnife.Setter<View, Boolean>() {
        @Override
        public void set(View view, Boolean aBoolean, int i) {

                if(aBoolean==false){

                    view.setClickable(false);

                }


        }
    };


    @OnClick(R.id.buttonFirst) void clickEvent(){   // tıklanma eventini kısaltarak kod fazlalığını azalttık

        ButterKnife.apply(buttons_list,changeColor);
    }

    @OnClick(R.id.buttonSecond) void controlClick(){

        ButterKnife.apply(buttons_list,disableButtons,false);
    }

   /* @OnClick(R.id.buttonSecond) void showToastSecond(){

        Toast.makeText(getApplicationContext(),"İkinci buton tıklandı",Toast.LENGTH_LONG).show();
    }

    @OnClick(R.id.buttonThird) void showToastThird(){

        Toast.makeText(getApplicationContext(),"Üçüncü buton tıklandı",Toast.LENGTH_LONG).show();
    }*/


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.bind(this);
    }
}

Evet arkadaşlar bu dersimizin de sonuna geldik. Özetleyecek olursam, Butter Knife sayesinde kod tekrarından kurtulduğumuz gibi pratik çözümlere de ulaşmış oluyoruz. Özellikle List yapısında view leri gruplayıp kullanabileceğimiz gibi, her view in tıklama eventini kontrol edebiliyoruz. Ayrıca, Activity dışında bir yapıyı oluştururken olsun (örnek: Fragment ) , Adapter yapısını oluştururken olsun her yerde Butter Knife kütüphanesinin özelliklerini kullanabiliriz.

Bu kütüphane ile ilgili ayrıntılı bilgiye ulaşmak isterseniz aşağıdaki linklerden faydalanabilirsiniz.

https://github.com/JakeWharton/butterknife ,  http://jakewharton.github.io/butterknife/  )

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..

Tüm Android Ders, Proje ve Kaynak Kodlar için tıklayınız.

2

Alper Beyler

Yüksek Lisans: Çankaya Üniversitesi / Bilgisayar Mühendisliği
Lisans: Çankaya Üniversitesi / Bilgisayar Mühendisliği (4/3.30) (2010-2014)
Lisans : Viyana Teknik Üniversitesi / Bilgisayar Bilimleri (2013)

11 Yorum

    • kullanıp kullanmamak size kalmış sonuçta adamlar böyle bir kütüphane ortaya çıkarmışlar bence kullanışlı ve kolay

    • Tabi alışkanlıkları terk etmek kolay değil, şimdilik bende sizin gibi düşünüyorum 🙂

  • ben projemde kullanmıştım bahsettiğiniz gibi kod fazlalığından kurtarıyor , performans açısından normal şekilde kullanmaya göre daha hızlı olduğunu duymuştum doğru mudur ?

    • yukarıda belirtmiş olduğum gibi run-time sırasında annotation lar daha oluşmamış oluyor ve annotation processor ile kütüphane işlemindeki @Bind vb. işlemler tetikleniyor hem kod fazlalığının atılması hem de çalışma prensibi yüzünden de performans olarak daha hızlı

    • sizin yazacağınız kodu proje derlenirken kendisi yazıyor. yük bindirmez ama hızlandırması doğru değil, en azından profesyonel birine göre. acemiler bazı hatalar yapabilir en azından onu önler.

  • hocam dersiniz için teşekkürler sitenizi severek takip ediyorum , bir sorum olacak square in çıkarmış olduğu Retrofit kütüphanesi ile ilgili bir ders yayınlayabilir misiniz ?

  • butterknife.Bind son sürüm butterKnife kütüphanesi ile kullanılamıyor ve hata veriyor.

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?