4 Şubat 2012 Cumartesi

Android ile Reflection (Android and Reflection)

Merhaba, (Hello)

Android ile ilgili yazılarımıza "reflection - yansıma" konusuyla devam ediyoruz. Aslında bu konuyu android için özelleştirmek çok mantıklı olmasa da android ile ilgili yazılan türkçe makaleler arasında örnek teşkil etmesi bakımından değinmek faydalı olacaktır diye düşünüyorum. Keza reflection zaten gerek java gerekse de .net geliştiricilerinin zaman zaman projelerinde kullandıkları önemli bir kütüphane. Dilerseniz konuyu biraz daha genel boyuta taşıyarak -bilakis daha önceden hiç kullanma fırsatı olmayan arkadaşlar için- kısa bir şekilde reflection'ın ne olduğu ve ne işe yaradığından bahsederek başlayalım. Reflection çok basit anlamda, herhangi bir nesnenin üye elemanlarına çalışma zamanında (runtime) ulaşıp, bu elemanların çağrılmalarına (invoking) imkan veren yapıdır. Reflection'ın avantaj ve dezavantajlarına girmek istemiyorum, internette bir çok kaynaktan bunları zaten detaylıca öğrenmek mümkün yalnız konumuz dışında olsa da belirtmekte fayda gördüğüm iki madde olacak. Bunlardan ilki reflection konusunda C# ile Java arasında bilinmesi gereken belki de en temel farklılık ile ilgili.
(We are continuing to talk about android with the "Reflection". Basically there are a lot of C# or Java developers who work with it on their projects time to time so it's a keypoint for both side not just Android. In a very simple manner the reflection is the ability to discover the members of a class and to invoke methods at runtime. I don't want to talk about advantages or disadvantages of the reflection because there are a few sources that may help you to lead what is it about on the internet but for a general knowledge I would like to mention two important things about differences between c# and java reflection)
  1. C#'ta reflection assembly seviyesinde olmaktayken, Java'da class seviyesinde uygulanmaktadır. .NET'te assemblyler dll'lerde tutulduğundan dolayı assembly load edilerek yapılırken java da class'ın kendisine erişim sağlanarak gerçekleştirilir. (Reflection in C# is done at the assembly level while reflection in Java is done at the class level. Since assemblies are typically stored in DLLs, one needs the DLL containing the targeted class to be available in C# while in Java one needs to be able to load the class file for the targeted class.)
  2. .NET'te ilgili nesnenin metadatası System.Type nesnesinde enkapsüle edilirken Java'da java.lang.Class nesnesi içerisinde enkapsüle edilir. (To retrieve the metadata class from an instance of the target class, the getClass() method is used in Java while the GetType() method is used in C#)
Type x = typeOf(y); // C# 
Class x = y.class; //Java 
İkinci madde de belirtmiş olduğum nedenden dolayı biz de android'de reflection ile uğraşırken metadatasına ulaşmak istediğimiz bütün nesnelerin enkapsüle edilmesi işlemi esnasında Class nesnesini kullanıyor olacağız. (We are going to use Class object while encapsulating objects on Android because of the reason described section two)
Class x = Object.class;
Constructor[] constructors = x.getDeclaredConstructors();
Field[] fields = x.getDeclaredFields();
Method[] methods = x.getDeclaredMethods();
for (Constructor constructor : constructors) {  
     //constructorlar
} 
for (Field field : fields) {
    //fieldlar 
}
for (Method method : methods) {
    //methodlar
}    

Android CodeBehind'da bir TextView nesnesi yaratırken yaptığımız işlem (Creating a TextView from codebehind on Andriod)
TextView x = new TextView(this); // constructor'a context geçiliyor.

Çalışma zamanında reflection ile yukarıdaki olayın gerçekleştirilmesi: Runtime'da bir TextView nesnesi yaratırken yaptığımız işlem -Constructor'a ulaşmak- (Creating a TextView from codebehind at runtime with using reflection)
String x = TextView.class.toString().replace("class ", "");
Class<?> cls = Class.forName(x);
Class<?> param[] = new Class[1];
param[0] = Context.class; //Context=o an ki context ==> [activity.class]
Constructor<?> ct = cls.getConstructor(param);
Object paramVal[] = new Object[1];
paramVal[0] = context;
Object retobj = ct.newInstance(paramVal); //constructor'a context geçilerek TextView'ın yeni bir instance'ı yaratıldı.
Çalışma zamanında reflection ile yarattığımız TextView nesnesinin setText() methoduna erişiyoruz (Reaching to setText() method at the runtime)
Class methodParam[] = new Class[1];
methodParam[0] = java.lang.CharSequence.class;
Method method = cls.getMethod("setText", methodParam);
Object arglist[] = new Object[1];
arglist[0] = new String("BU TEXTVIEW RUNTIME'DA OLUŞTURULDU");
method.invoke(retobj, arglist); //void method call edildi. 

Bu aşama ve sonrasında yapılacaklar istenen şeye göre elbette değişkenlik arzedecektir, biz burada örnek olması açısından retobj isimli nesnemizi View'a cast ederek ilgili layout'a ekleyeceğiz. (The rest is up to you, I casted retobj to View and added it to a linearLayout as following to set an example)

View v = (View)retobj;
linearLayout.addView(v);

İyi çalışmalar,
(Good work)