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