Android: findViewById Fonksiyonu Yerine Alternatif Çözüm

Bilindiği üzere deklaratif yöntemle tasarlanan ekranlarda kullanılan GUI elemanlarının programatik nesnelere dönüştürülmesi amacıyla findViewByID() isimli fonksiyon (metot) kullanılmaktadır. Bu fonksiyon kullanılarak yapılan işlem, özellikle XCode ya da Visual Studio gibi güçlü RAD (Rapid Application Development) özelliklerine sahip araçları kullanan programcılar tarafından sıkça eleştirilmektedir. Her ne kadar bu işlemi kolaylaştırmaya yönelik sonradan birtakım üçüncü parti eklentiler (ButterKnife) gibi tasarlanmış ise de (yazar da dahil olmak üzere) bu araçlar geniş kitleler tarafından kabul görmemiştir.

Bu noktada daha özgün bir çözüm kullanmak isteyen okurlar için reflection ve annotation’lara dayalı olan yöntem tercih edilebilir.

Dikkat: Annotation konusuna yabancı ya da kendisini bu konuda yetersiz hisseden okurlar öncelikle ek bölümdeki annotation’ların anlatıldığı kısmı okumalıdırlar.   

Sözgelimi aşağıdaki gibi bir XML kodu ile deklaratif olarak tasarlanmış bir ekrandaki GUI elemanlarını ele almak gerekirse:

<LinearLayout android:id=”@+id/pnl” >

    <TextView android:id=“@+id/txt”

        android:text=“TeknolojiDergisi.net” … />

    <Button android:id=“@+id/btn”

        android:text=“TEST” … />

</LinearLayout>

Buradaki (pnl, btn, txt) id’li GUI elemanları için nesne yaratılmak istenildiğinde normalde aşağıdaki gibi bir kod satırı yazılmaktadır:

TextView txt = (TextView) findViewById(R.id.txt);

Oysa bu kod aşağıdaki şekle indirgenebilir:

@GUI(R.id.txt)

private TextView txt;

Burada kullanılmış olan @GUI annotation’ı aşağıdaki gibi tasarlanmıştır:

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface GUI

{

    int value() default 1;

}

@Target ve @Retention ise yine birer annotation olup, sırasıyla @GUI annotation’ının sadece sınıfın field’ları yani veri elemanları üzerinde kullanılabileceğini diğeri ise çalışma zamanında ele alınacağını anlatmaktadır.  

@GUI isimli annotation’ının kullanıldığı bir veri elemanının yaşayan bir nesne haline getirilmesini ise GuiUtil isimli sınıfın FindElements() isimli statik fonksiyonu -reflection mekanizması- yoluyla yapmaktadır.   

public class GuiUtil

{

    public static void FindElements(Activity activity)

    {

        try

        {

            for (Field f : activity.getClass().getDeclaredFields())

            {

                GUI gui = f.getAnnotation(GUI.class);

                if (gui != null)

                {

                    f.setAccessible(true);

                    f.set(activity, activity.findViewById(gui.value()));

                }

            }

        }

        catch (Exception ex)

        {

            Log.e(“err”, ex.getMessage());

        }

    }

}

Görüldüğü gibi FindElements() fonksiyonu, parametresine aldığı Activity nesnesinin, üzerinde @GUI annotation’ının kullanılmış olduğu veri elemanlarını dinamik olarak elde etmekte ve bunları içsel olarak yine findViewById() fonksiyonunu kullanarak nesne haline getirmektedir. Bu noktada yöntemin kullanışlı ve efektif olup olmadığı okuyucunun takdirine bırakılmıştır. Son kertede bu mekanizmanın Activity içerisindeki kullanımına bir örnek aşağıda verilmiştir:

public class MainActivity extends AppCompatActivity

{

    @GUI(R.id.pnl)

    private LinearLayout pnl;

    @GUI(R.id.btn)

    private Button btn;

    @GUI(R.id.txt)

    private TextView txt;

    private void btn_Click()

    {

        btn.setOnClickListener(

                new View.OnClickListener() {

                    @Override

                    public void onClick(View view) {

                        pnl.setBackgroundColor(Color.BLUE);

                        txt.setText(“SiberNext.com”);

                    }

                }

        );

    }

    @Override

    protected void onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        GuiUtil.FindElements(this);

        btn_Click();

    }

}

Reklamlar

Python ile Singleton Patern’i

Pratikte herhangi bir sınıf türünde birçok kez nesne örneği (object instance) yaratmak istenebilir. Bu işlem normal yollarla yapıldığında yaratılan her bir nesne örneği için bellekte farklı bir yer tahsis edilecek ve nesnenin veri elemanlarında taşıyacağı değerler yani durum bilgisi bu alanlara yerleştirilecektir. Ancak bazı durumlarda ve bazı nesneler için kaç kez nesne örneği yaratılmak istenilirse istenilsin ilk seferinde yapılan yaratma işleminden sonra -yaratma işlemi tekrar edilse bile- yeni bir nesne daha yaratılmaksızın hep bu ilk nesne örneğinin kullanılmasına ihtiyaç duyulabilir. Başka bir deyişle söz konusu sınıf nesnesinin sadece bir kereliğine yaratılıp, daha sonra sürekli olarak kendisinin kullanılması isteniyor olabilir. İşte bu ihtiyacı karşılayan tasarım çözümünün ismi; Singleton patern’idir.

Singleton Patern’inin Uygulanmasıyla İlgili Esaslar

  1. Bu paternin uygulandığı sınıflarda, kendi türünde private ve static bir nesne olmalıdır. Statik olmasının sebebi; taşıyacağı adresin nesneden bağımsız ve sabit şekilde kullanılması ihtiyacıdır. (Örnekteki ismi; m_smp’dir)
  2. Söz konusu sınıfın türündeki nesnenin yaratılışı sadece bir kez yapılmak istendiği için sınıfın init fonksiyonu (initializer’ı) private tanımlanarak kullanıcı taraftan gizlenmelidir. Böylece sınıfı kullanacak olan programcı init() fonksiyonunu doğrudan çağıramaz hale gelir.
  3. init() fonksiyonunun bir anlamda yerini alacak olan, bir class üye fonksiyon (singleton nesne yaratıcı fonksiyon) olmalıdır. Bu fonksiyon 1. maddede anlatılmış olan statik nesnenin taşıyacağı adresi geriye döndürecek şekilde yazılmalıdır. Ancak kuşkusuz bu değer geriye döndürülmeden önce nesne için tahsisat yapılmış olmalıdır ki tahsisatın başlangıç adresi bu nesneye atansın ve geriye döndürülebilsin. Bu işlemler söz konusu fonksiyon içerisinde gerçekleştirilir. (Örnekteki ismi; CreateObject()’tir.)

class Sample:

    m_Smp = None

    class __Sample:

        def __init__(self):

            self.val = None

            print(“Sample nesnesi yaratıldı”)

    #CreateObject

    def __new__(cls):

        if not Sample.m_Smp:

            Sample.m_Smp = Sample.__Sample()

        return Sample.m_Smp

    #GetData

    def __getattr__(self, name):

        return getattr(self.m_Smp, name)

    #SetData

    def __setattr__(self, name):

        return setattr(self.m_Smp, name)

obj1 = Sample()

obj2 = Sample()

obj3 = Sample()

obj1.val = 7877

print(“obj1-Data: ” + str(obj1.val))

print(“obj2-Data: ” + str(obj2.val))

print(“obj3-Data: ” + str(obj3.val))

print(“———–“)

obj2.val = 1999

print(“obj1-Data: ” + str(obj1.val))

print(“obj2-Data: ” + str(obj2.val))

print(“obj3-Data: ” + str(obj3.val))

Bu durum şöyle yorumlanabilir; 7877 değeri obj1 ile set edildikten sonra, diğer nesneler de aynı veriyi referanse ettiklerinden dolayı, veri alındığında hep aynı değerlere ulaşılmaktadır. Keza obj2 ile 1999 değeri set edilip, veri tekrar alındığında bu kez üç sefer de 1999 değerine ulaşılmaktadır.

Component Tester İncelemesi

Ali Express’ten satın aldığım component test cihazının incelemesini bu bölümde izleyebilirsiniz. Pek çok devre elamanını (transistör, diyot, direnç, kondansatör, bobin vb) test edebilen, uçlarını belirleyebilen, çeşitli elektriksel karakteristiklerini gösteren renkli ekranlı bu cihaz aynı zamanda frekans sayıcı, kare dalga osilatör hatta voltmetredir.
Bu cihazla DHT11 gibi bir sensörü kullanarak sıcaklık ve nem ölçmesi yapılabileceği gibi, InfraRed alıcısı (sensör) ile IR kodları decode edilebilmektedir.

Silikon vs Silisyum?

Okulda elektronik derslerini anlatırken sıkça ve mecburen yarı iletkenlerden hatta katı hal fiziğinden (üniversitede zorlandığım bir dersti) bahsetmek zorunda kalıyorum.  Malûmunuz yarı iletken olarak bilinen ve kullanılan 2 element vardır; Germanyum ve Silisyum.

Silisyum

Modern yarı iletken elektroniğinde Germanyum görece kötü karakteristikler gösterdiğinden dolayı artık kullanılmamaktadır. Yerine tercih edilen Silisyum ise ismi yüzünden bolca kafa karışıklığına neden olmaktadır. 

Yarı iletkenler

Türkiye fizik ve elektronik camiasında tercih edilen isim; (benim gördüğüm kadarı ile) Silisyumdur. Ancak özellikle Amerikalılar bu elemente daha çok Silicon demeyi tercih eder hatta meşhur Silicon Valley (Silikon Vadisi) isimli yer, bu bölgede konuşlanmış özellikle yarı iletken üreticisi teknoloji firmaları yüzünden bu ismi almıştır. Yani bu vadi (en azından benim bildiğim kadarı ile) Silikon veya Silisyum elementinin dünyada en çok bulunduğu yer değildir.  

Özetle Silikon ve Silisyum aslında aynı elementin isimleridir. Söz konusu element periyodik tablonun 14. sırasında olup, doğada nadiren saf halde bulunmakta daha çok Silikon Dioksit ya da bilinen diğer isimleri ile (Silika veya Quartz) kristalleri şeklinde bulunmaktadır. Bu da bildiğimiz kumdur.

phone-sand

Silikon ya da Silisyum aynı zamanda doğada Oksijenden sonra en çok bulunan 2. elementtir. 

depositphotos_43048227-stock-photo-silicone-gun

Meslekten olmayan bir Türk insanı için Silisyum ve Silikon arasındaki kafa karışıklığı ise silikonu daha çok dolgu maddesi, yapıştırıcı hatta tıp, kozmetik alanlarında kullanılan şekilleriyle tanımasından ileri gelir. Buradaki nüans; Silicon ve Silicone arasındaki farktır. Yukarıda sayılan şekillerde kullanılan madde yani Silicone ise aslında doğal olmayan bir sentetik polimerdir.    

silikon-dudak_170346