31 Mayıs 2011 Salı

Android Serisi 5. Bölüm - List Activity - Custom Adapter

Merhaba,

Kaldığımız yerden list activity ile devam ediyoruz. Her zaman olduğu gibi yine lafı hiç uzatmayacağım, örnek bir senaryo ile konuya bodozlama giriş yapıyoruz. İşte senaryo; kullanıcının karşısına Türk futbol takımlarının olduğu bir liste sunacağız, kullanıcı listedeki itemlardan birine bastığında seçimini ekrana yansıtacağız, eğer bu itemlardan birine uzunca basarsa silmek isteyip istemediğini soracak ve ona göre aksiyon alacağız. Kısaca bugüne kadar öğrendiklerimizi hafifçe bir toparlamış olacağız. Hadi başlayalım.

Önce yeni bir proje ve takimlar isimli yeni bir aktivite yaratıyoruz yalnız bu aktivitenin öncekilerden bir farkı olacak. Bu aktivitemiz öncekiler gibi Activity class'ından değil ListActivity class'ından extend edilecek.

Daha sonra custom adapter'ımızı oluşturmak için layout > row.xml'imizi yaratıp aşağıdaki gibi düzenliyoruz.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="@+id/imgLogo"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6dip"
android:src="@drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="@+id/lblIsim"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
/>
<TextView
android:id="@+id/lblSampiyonlukSayisi"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
/>
</LinearLayout>
</LinearLayout>

Bu işlemin ardından drawable klasörlerimize 32x32 takım logolarımızı atıyoruz.



Tamam sıra geldi Takım classımızı oluşturmaya, resimdeki gibi src klasörünün altında Takim adinda bir class yaratıyor ve aşağıdaki gibi kodluyoruz.



package com.tft;

public class Takim {

//constructorlar
public Takim(){}
public Takim(String isim, int sampiyonluk_sayisi,String logo){
this._isim = isim;
this._sampiyonlukSayisi = sampiyonluk_sayisi;
this._logo = logo;
}

//fieldlar
private String _isim;
private int _sampiyonlukSayisi;
private String _logo;

//propertyler
public String getIsim(){
return _isim;
}
public void setIsim(String isim){
_isim = isim;
}

public int getSampiyonlukSayisi(){
return _sampiyonlukSayisi;
}
public void setSampiyonlukSayisi(int sampiyonlukSayisi){
_sampiyonlukSayisi = sampiyonlukSayisi;
}

public String getLogo(){
return _logo;
}
public void setLogo(String logo){
_logo = logo;
}
}

Şimdi de sıra customadapter'ımızda, yine src klasöründe TakimAdapter adinda bir class oluşturup aşağıdaki gibi düzenliyoruz.

package com.tft;

import java.util.ArrayList;

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;

class TakimAdapter extends ArrayAdapter<Takim> {
private Context context = null;
private ArrayList<Takim> items;

public TakimAdapter(Context context, int textViewResourceId, ArrayList<Takim> items) {
super(context, textViewResourceId, items);
this.items = items;
this.context = context;
}

public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
//inflaterlar xml inputu codebehind'da nesneye çevirmemizi sağlarlar.
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(com.tft.R.layout.row, null);
}
Takim takim = items.get(position);
if (takim != null) {
//listemizde gözükecek kontrollerimizi set ediyoruz.
TextView lblIsim = (TextView) v.findViewById(com.tft.R.id.lblIsim);
TextView lblSampiyonlukSayisi = (TextView) v.findViewById(com.tft.R.id.lblSampiyonlukSayisi);
ImageView imgLogo = (ImageView)v.findViewById(com.tft.R.id.imgLogo);
if (lblIsim != null) {
lblIsim.setText(takim.getIsim()); }
if(lblSampiyonlukSayisi != null){
lblSampiyonlukSayisi.setText("Şampiyonluk Sayısı: "+ takim.getSampiyonlukSayisi());
}
if(imgLogo != null){
//logolarımızın IDlerini alıyoruz.
int logoID = context.getResources().getIdentifier(takim.getLogo(), "drawable", context.getPackageName());
imgLogo.setImageResource(logoID);
}
}
return v;
}
}


Artık custom adapterımızda, Takim class'imizda hazır. Takimlar ListActivity'mizi yapılandırabiliriz.

package com.tft;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;

public class Takimlar extends ListActivity { //ListActivity classından türetildi

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//takimlari kendi yarattığım row bazında oluşturuyorum
final ArrayAdapter<Takim> adapter = new TakimAdapter(this, com.tft.R.layout.row, getTakimlar());
setListAdapter(adapter);

//itemlara tıklandığında yapılacak işlem
getListView().setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View v, int position,
long arg3) {
Takim oTakim = (Takim)parent.getItemAtPosition(position);
Toast.makeText(getBaseContext(),
oTakim.getIsim(),
Toast.LENGTH_SHORT).show();
}
});

//itemlara uzun basıldığında yapılacak işlem
getListView().setOnItemLongClickListener(new OnItemLongClickListener(){
public boolean onItemLongClick(AdapterView<?> parent, View v,
int position, long arg3) {
final Takim oTakim = (Takim)parent.getItemAtPosition(position);
//burada AlertDialog.Builder'ın constructor'ına dikkat edin. Listactivitymizin context'ini atıyoruz.
AlertDialog.Builder builder = new AlertDialog.Builder(Takimlar.this);
builder.setMessage("Bu takımı silmek istediğinizden emin misiniz?");
builder.setPositiveButton("Evet", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
adapter.remove(oTakim);
adapter.notifyDataSetChanged();
}
});
builder.show();
return false;
}

});
}

//Takimlar ekleniyor
private ArrayList<Takim> getTakimlar(){
ArrayList<Takim> takimList = new ArrayList<Takim>();
takimList.add(new Takim("Galatasaray",17,"gs"));
takimList.add(new Takim("Fenerbahçe",18,"fb"));
takimList.add(new Takim("Beşiktaş",13,"bjk"));
takimList.add(new Takim("Trabzonspor",6,"ts"));
takimList.add(new Takim("Bursaspor",1,"bs"));
return takimList;
}

}

Çalıştırdığımızda projemizin ekran görüntüleri aşağıdaki gibi olmalı.





Bir sonraki örnek uygulamamızda görüşmek üzere derken tekrar hatırlatmak istiyorum sorularınızı çekinmeden sorabilirsiniz, fırsat bulduğum müddetçe yanıtlamaya çalışacağım.

Dosya İsmi: ListActivityOrnek.rar
Dosya Boyutu:74.59 KB

30 Mayıs 2011 Pazartesi

Bunun üzerine Fifa oynamaya devam edenler oldu...

Skora aldanmamak lazım. Direklerden dönenler, hakem sıbobçek'in çalmadığı düdükler... ortasahayı geçemeyen, kendi sahasına hapsolmuş ezik bir Sunderland. Büyük Liverpool, yürüyedur...

Android Serisi 4. Bölüm - AlertDialog.Builder Sınıfı ve Dialog Kutuları

Merhaba arkadaşlar, tekrar birlikteyiz.

Konumuz gayet basit olmakla birlikte yazılım uygulamalarının da olmazsa olmazlarından biri. Biz yine lafı uzatmadan örnekle hemen işe koyulalım.

Senaryo şu; bir düğme var, kullanıcı düğmeye bastığında karşısına bir dialog box çıkacak. Sorulan soruya evet derse title değiştirilip rengi sarıya dönüştürülecek. Hayır derse bir mesajla bu seçimi kullanıcıya belirtilecek.

BuilderOrnek adinda bir proje yaratıyorum. Activity'imin adı ise Main.

Layout > main.xml dosyasını aşağıdaki gibi editliyorum.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:id="@+id/lblTitle"
/>

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="BuilderDeneme"
android:text="Tıklandığında Alert oluşacak"
android:id="@+id/btnBuilder"
/>
</LinearLayout>

Son olarak Main.java activity'imi açıp aşağıdaki gibi düzenliyorum.

package com.builderornek;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class Main extends Activity {
private final Context context = this; //context'imizi globalleştiriyoruz.

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

//btnBuilder'a tıklandığında aşağıdaki method çalışacak.
public void BuilderDeneme(final View v){
//Dialog nesnesi oluşturuluyor.
AlertDialog.Builder builder = new AlertDialog.Builder(context);
//Kullanıcıya gösterilecek mesaj oluşturuluyor.
builder.setMessage("Devam ederek başlık yazısını değiştirmek istediğinizden emin misiniz?");
//Cancel buttonu iptal ediliyor (örnek olması amacıyla koydum)
builder.setCancelable(false);
//Kullanıcı tamam diyerek devam etmek istediğinde (true response'unda yapılacaklar.)
builder.setPositiveButton("Evet", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
TextView lblTitle = (TextView)findViewById(R.id.lblTitle);
lblTitle.setTextColor(Color.YELLOW);
lblTitle.setText("baslik değiştirildi ve rengi sarı oldu.");
}
});

//kullanıcı iptal diyerek devam etmek istediğinde. (false)
builder.setNegativeButton("Hayır", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "Bir değişiklik yapılmadı", Toast.LENGTH_SHORT).show();
}
});

//builder dialogumuzu kullanıcıya gösteriyoruz.
builder.show();
}

}

ve işte sonuç;



Dosya İsmi: BuilderOrnek.rar
Dosya Boyutu:41.49 KB

25 Mayıs 2011 Çarşamba

Android Serisi 3. Bölüm - Values klasörü ve Localization

Arkadaşlar merhaba, android serisinin üçüncü bölümüyle tekrar beraberiz. İsterseniz hiç uzatmadan direk values klasörünün ne işe yaradığını belirterek başlayalım. Özetle values klasörü string sabitlerden oluşan xml dosyaları içerir. Genelde localization ve başka nesnelere yeni değerler atamak amacıyla kullanılır. Localization'ı zaten birlikte yapacağız ancak başka nesnelere yeni değer atamak cümlesiyle neyi kastediyoruz onu kısaca açıklayalım.

Mesela resource'a kendi yaptığınız renk kodunu ekleyebilirsiniz. Values klasörüne colors.xml adıyla yeni bir Android XML dosyası oluşturup aşağıdaki kodu içerisine kaydedin.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="baslik">#AAFFFF99</color>
<color name="satir_1">#FF0000FF</color>
<color name="satir_2">#90FF0000</color>
<color name="uyari">#AA0000FF</color>
</resources>

Artık bu color elemanlarını name tag'inde atadığınız değere göre kullanmanız için hiçbir engel yok. R.color.baslik şeklinde çağırmanız yeterli.

LOCALIZATION

2. bölümde yapmış olduğumuz örnek uygulamayla devam edelim. Orada hardcoded eklediğimiz bölümleri dinamikleştirmiş olacağız. Bunun için values klasöründe aşağıdaki gibi yeni bir android.xml dosyası oluşturun.



Not: Benim emulatörümde türkçe dil desteği olmadığından dolayı -ki büyük ihtimal sizinkinde de olmayacaktır- fransızca'ya göre ayarlama yapıyor olacağım.

şimdi values klasörümüz içindeki string.xml dosyasını açıp içini aşağıdaki gibi değiştiriyoruz.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Our Android Programme!</string>
<string name="app_name">Sample App Login Screen</string>
<string name="lblUsername">Username: </string>
<string name="lblPassword">Password: </string>
<string name="lblBtnGiris">Login</string>
<string name="msg_Login_1">Invalid Username or Password!</string>
<string name="msg_Login_2">Wellcome Dear</string>
</resources>

aynı şekilde values-fr klasörü içerisindeki string.xml dosyasını da aşağıdaki gibi değiştiriyoruz.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Android Programımız</string>
<string name="app_name">Deneme App Giriş Ekrani</string>
<string name="lblUsername">Kullanıcı Adı: </string>
<string name="lblPassword">Şifre: </string>
<string name="lblBtnGiris">Giriş</string>
<string name="msg_Login_1">Geçersiz kullanıcı adı veya parola!</string>
<string name="msg_Login_2">Hoşgeldiniz Sayın</string>
</resources>

xml tarafında yapacağımız son değişiklik layout klasörü içerisinde bulunan main.xml dosyasındaki tüm viewların text attributelerini aşağıdaki gibi değiştirmek. Ben sadece bir tanesini örnek olarak koyuyorum.

<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="2"
android:text="@string/lblUsername"
android:gravity="right"
/>

Artık xml tarafında yapacaklarımız bitti. Şimdi kod tarafına geçelim. Toast.makeText methodumuzu aşağıdaki gibi değiştirelim.

Toast.makeText(getApplicationContext(), R.string.msg_Login_2 + ' ' + txtUsername.getText().toString(), Toast.LENGTH_SHORT).show();

Şimdi uygulamamızı hiç dil değişikliği yapmadan çalıştıralım.


Şimdi de dili fransızcaya getirip uygulamamızı tekrar çalıştıralım.


Dosya İsmi: Activity_View_Toast_Localization.rar
Dosya Boyutu:43.97 KB

23 Mayıs 2011 Pazartesi

Android Serisi 2. Bölüm - Activity, View, Toast kavramları

Merhaba arkadaşlar,
Android serimizin 2. bölümüyle tekrar beraberiz. Önceki bölümümüzde android'in temellerinden ve bu temel kavramlar içinde en önemlisi olan activity'nin yaşam döngüsünden bahsetmiştik. İkinci bölümde activity, view ve toast (messagebox) kavramlarıyla android ile program geliştirmeye girmiş olacağız.

Örnek bir uygulamanın yerini başka hiçbir şey tutamaz düşüncesiyle konuyu uzatmadan tüm bu kavramları tam manasıyla anlayabileceğimiz bir senaryo geliştiriyoruz. Senaryomuza göre kullanıcı, yazacağımız bir ekran ile uygulamaya login olmaya çalışacak, girilen bilgiler kontrol edilip kullanıcıya mesaj dönülecek.

Dilerseniz öncelikle login ekranımızın tasarım kısmını oluşturalım ve bu sayede de viewlara girmiş olalım. Hemen aşağıdaki gibi bir android projesi oluşturarak işe başlıyoruz.


Evet projemizi oluşturduk, artık tasarım ekranımızı yapmaya yani viewlarla tanışmaya hazırız. Yazılım literatüründe Control olarak bildiğimiz yapılar Android dünyasında View ismiyle anılıyor. Edittext (textbox), Textview (label), button, checkbox, radiobutton, vs... gibi bir çok view bulunmakta. http://www.basic4ppc.com/forum/basic4android-getting-started-tutorials/7319-android-views-controls-dialogs.html bağlantısına tıklayarak viewları tek tek inceleyebilirsiniz. Biz örneğimizde 2 edittext, 2 textview, 2 LinearLayout ve 1 tane de button kullanacağız.

Android'de bir activity'nin tasarım ekranını xml uzantılı layout dosyalarıyla gerçekleştirebiliyoruz. (Bunun yanında dilerseniz codebehind'dan da layout'unuzu oluşturabilirsiniz). Bu dosyalar sol taraftaki resimde de belirtildiği üzere Proje > res > layout dizininde bulunmaktadırlar. Dilerseniz tam bu noktada kısaca Res klasöründen bahsedelim. Res klasörü default olarak 5 klasör içerir. Bunlardan ilk üçü (drawable klasörleri) ikonların hangi çözünürlük tipine göre çizileceğini belirtir. Eğer yaptığınız uygulama ikon, resim, vb içeriyorsa ve bu uygulama android işletim sistemine sahip tüm aygıtlarda çalıştırılmak isteniyorsa o zaman tüm dpi türlerine göre bu dosyaları oluşturup ilgili klasörlerine atmak zorundasınız. Amacınız basit bir uygulama ise hepsini bir klasörde toplamanız da mümkün. Android ile IPhone arasındaki en büyük farklılıklardan biri android'de fragmantasyonun çok fazla olması. Bu da bu tür konularda uygulama geliştiriciler için büyük bir dezavantaj oluyor. Bu 3 drawable klasöründen hemen sonra Layout ve Values klasörlerini görüyoruz. Layout, az önce de belirttiğimiz gibi tasarım dosyalarının tutulduğu klasör. Values ise aslında yeri geldiğinde daha detaylıca değineceğiz ancak şimdilik hakkında bilmeniz gereken şey localization'dan tutun da hardcoded kötü kodlamanın önüne geçmenize imkan verecek kadar kullanışlı xml dosyalarımızın barındığı kısım olmasıdır.


main.xml dosyasına tıkladığınızda karşınıza bir tasarım editörü Graphical Layout çıkacak. Ancak biz tasarımımızı yaparken graphical layout yerine -bence- daha anlaşılır ve esnek olan (graphical layout'un hemen sağında göreceğiniz) main.xml tab sekmesini kullanacağız.

Aşağıdaki kodu main.xml ekranındaki default gelen kodla değiştirin.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50px"
android:weightSum="3"
android:layout_margin="10dp"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="2"
android:text="Kullanıcı Adı: "
android:gravity="right"
/>
<EditText
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:id="@+id/txtUsername"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50px"
android:weightSum="3"
android:layout_marginTop="-10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="2"
android:text="Şifre: "
android:gravity="right"
/>
<EditText
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:id="@+id/txtPassword"
android:password="true"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50px"
android:weightSum="3"
android:layout_marginTop="-10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="2"
android:text=""
/>
<Button
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:id="@+id/btnGiris"
android:text="Giriş"
android:layout_gravity="right"
/>
</LinearLayout>
</LinearLayout>


Önce tüm ekranı kaplayacak bir LinearLayout daha sonra da onun içine satır mantığını oluşturacak diğer LinearLayoutları koyduk. Aralarındaki tek fark en dıştakinin orientation=vertical, diğerlerinin horizontal olması. LinearLayout'ı HTML elemanlarından birine benzetmemiz gerekirse en uygunu DIV olacaktır sanırım. Sonrasında sırasıyla TextView (label) ve EditText (textbox) kontrollerimizi ekledik. Atamış olduğum attributeleri değiştirerek nasıl çalıştığını daha iyi anlarsınız diye düşünüyorum. Burada dikkat etmeniz gereken ID atamasının nasıl yapıldığı keza kontrole bu atamış olduğumuz ID ile ulaşacağız.

Sonuç olarak ekran görüntümüz aşağıdaki gibi olmalı.


Artık kod tarafına geçebiliriz. Proje menümüzdeki src klasörünün altında bulunan Login.java isimli classımızı (activity) açıyoruz ve aşağıdaki kodları ekliyoruz.

package com.denemeapp;

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

public class Login extends Activity {

private final String loginName="mustafaguven", loginPassword="123456";
private EditText txtUsername, txtPassword;
private Button btnGiris;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); //main.xml isimli dosyamızın çizilmesi gerektiği belirtildi.

//kontrollerimizi yakaladık
txtUsername = (EditText)findViewById(R.id.txtUsername);
txtPassword = (EditText)findViewById(R.id.txtPassword);
btnGiris = (Button)findViewById(R.id.btnGiris);

//button'ın onclick anında işlem yapmak için bir listener set ettik
btnGiris.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
//kullanıcı adı ve şifre kontrolümüzü yaptık
if(txtUsername.getText().toString().contentEquals(loginName)
&& txtPassword.getText().toString().contentEquals(loginPassword)){
//kullanıcıya mesaj vermek için Toast nesnesini kullandık
Toast.makeText(getApplicationContext(), "Hoşgeldiniz Sayın " + txtUsername.getText().toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Yanlış kullanıcı adı veya şifre", Toast.LENGTH_SHORT).show();
}
}
});
}
}


ve sonuç...



Dosya ismi: Activity_View_Toast.rar
Dosya Boyutu: 41.66 KB

21 Mayıs 2011 Cumartesi

Android Serisi 1. Bölüm - Android'in Temelleri

Merhaba, uzun zamandır baştan sona android ile ilgili bir set hazırlayıp, siz değerli yazılımcı arkadaşlarımla paylaşmak istiyordum. Ancak yoğun çalışma temposu, bilgisayarımın dandikliği ve bir şeyler yazmaktan erinecek kadar tembel birisi olmam bu isteğimin bir türlü gerçekleşmemesine neden oldu.

Aslında görsel bir paylaşımda bulunmak yerine makale hazırlamak -bence- son derece yanlış bir tercih. Görsel bir eğitimin yerini başka hiçbir şeyin tutmayacağını düşünüyorum. Ancak şu an bilgisayarım bir nedenden ötürü ses kaydı yapamıyor. Bundan dolayı -en azından şimdilik-, makalelerle idare etmemiz gerekmekte. Bu paylaşımı, çözüm bulur bulmaz videolarla daha katılımcı ve hızlıca anlaşılır bir şekle sokacağımdan emin olabilirsiniz. Neyse lafı çok uzattık dilerseniz hemen konumuza girelim.

ANDROID'İN TEMELLERİ:

Bir Android Uygulaması Temelde Hangi Kavramlardan Oluşur?
  1. Activity: Uygulamadaki her bir ekran aslında bir activity'dir ve Activity class'ından extend edilir. .NET tarafındaki ASPX dosyasının Android'deki karşılığıdır diyebiliriz. Activityler, View nesnelerini kullanarak işlem gerçekleştirirler. 
  2. Service: Arkaplanda çalışırlar ve bu esnada Activitylerle veya datasource gibi diğer nesnelerle etkileşimde bulunabilirler. 
  3. Content Provider: Uygulamalar arası data paylaşımını sağlamak için kullanılır. Kısaca paylaşılabilir veri depolarıdır diyebiliriz.
  4. Intent: Activityler, serviceler, vs gibi nesneler arası mesajlaşmayı sağlayan yapılardır. (Activityler ile birlikte en çok kullanılan nesnelerden biridir)
  5. Broadcast Receiver: Uygulamayla ilişkili intentlerin dinlenmesine imkan sağlayan yapılardır.

Bir Android Uygulamasının Yaşam Döngüsü Nasıldır?
  1. Aktiftir: An itibariyle kullanıcı tarafından kullanılmakta olan uygulamadır.
  2. Aktif değildir ancak "Visible" konumdadır: O an aktif olarak kullanılmamakla beraber memory'de yaşamaya devam etmektedir. Transparan konumdadır diyebiliriz.
  3. Visible değildir ancak "Arkaplandadır": An itibariyle hiçbir servisinin kullanılmadığı uygulamadır. Android tarafından otomatik olarak dispose edilirler.
  4. Pasiftir (Inactive): Uygulama, Android tarafından kill edilmiştir.
Bu döngüyü kafada daha iyi canlandırabilmek için iskambil kağıtlarını tutan bir el örneğinin çok da yanlış olmayacağını düşünüyorum. Evet lütfen gözünüzün önüne aşağıdaki resimdeki gibi iskambil kağıtlarını tutan bir el getirin. Bu resme göre bir analoji kuracak olursak diyebiliriz ki kupa as aktif olan activity'dir. Diğerleri visible konumdadırlar. Maça kızı kupa as'ın yerine geçtiğinde maça kızı aktif konuma gelmiş olacaktır, last active activity (en son aktif olan activity) ise kupa as olmuş olacaktır. Bu şekilde düşünmeye devam edecek olursak belli bir süre sonra Android tarafından ilk kill edilecek uygulama kupa papaz olacaktır. (bknz: last-seen-first-killed pattern, http://mobworld.wordpress.com/2010/07/05/memory-management-in-android/)

 


ACTIVITY YAŞAM DÖNGÜSÜ
Activityleri kullanmadan önce activitylerin nasıl bir yaşam döngüsüne sahip olduklarını bilmemiz çok önemli. Yaşamı boyunca hangi eventlerin hangi zamanlarda raise edildiği ve bu esnada uygulamanın ne aşamada olduğunu bilmemiz uygulama geliştirme aşamasında bizleri çok daha bilinçli hareket etmeye sevk edecektir.

Bir activity'nin yaşam döngüsü aşağıdaki gibidir.


Aslında yukarıdaki şema herşeyi son derece açık bir şekilde anlatıyor. Ancak yine de biz üstünden bir özet geçelim. Şimdi, siz bir uygulamayı çalıştırmak için tetiklediğinizde bilmelisiniz ki önce onCreate event'i raise edilmiş olacaktır. Yani activity initiliaze edilecektir. Buradan sonra onStart eventi fırlatılır. onStart eventinde activity artık visible'dır ancak hala aktiflik söz konusu değildir, UI bilgisi burada uygulanır. onResume eventinde ise activity artık aktiftir. onResume'dan sonra bu şemada gösterilmeyen onSaveInstanceState eventine girilir. Bu evente gelen Bundle (web uygulamalarındaki session veya hashtable nesnesinin benzeri bir yapıdır), eğer proses uçurulmuşsa (kill edilir) veya restart edilmişse onCreate eventine UI state değişikliklerini gönderir. Daha sonra onPause eventine geçilir. Activity önplanda değil askıya alınmıştır yani artık aktif değildir. onStop eventinde activity kill edilmek için beklemekte, onDestroy'da onCreate eventinde initiliaze edilmiş tüm kaynaklar, tüm connectionlar (network ve database connectionları gibi) dispose edilmektedir. Bazı durumlarda onDestroy methodu call edilmeden de proses terminate olabilir.

Artık ne yaptıklarını bildiğimize göre hangi aşamada hangi methodu kullanmamız gerektiğini de söyleyebiliriz.

onCreate; UI ve class değişkenlerini oluştururken, kontrollere data bağlarken ve service veya thread oluştururken

onStop: animasyonları, threadleri, sensör dinleyicilerini (sensor listeners), GPS aramalarını, zamanlayıcıları, servisleri durdururken

onStart: UI visible olduğunda onStop eventinde kapatılmış olanları tekrar çalıştırmak amacıyla (Ilk açılış haricinde)

onPause: Broadcast Receiverları durdururken

onResume: Broadcast Receiverları tekrar çalıştırırken kullanın.

20 Mayıs 2011 Cuma

Java'daki final keyword'ü ve C#'taki karşılığı?

Arkadaşlar merhaba, çok kısa ama sanırım bir o kadar da yararlı bir yazı olacak. Java'da final keyword'ünün nerelerde kullanıldığına ve C#'taki karşılığına dair bilgi paylaşacağım. Beni bu yazıyı yazmama, çevremde tanık olduğum, final keyword'ü ile ilgili kavram karmaşasında kalmış arkadaşlar yöneltti. Peki nedir bu final keyword'ü ve herşeyden önemlisi ne işe yarar? Çok basitçe hemen açıklayalım.

Öncelikle .NETçiler için belirteyim, daha sonra iki tarafa da yabancı olan arkadaşlar için açıklamayı genişletebiliriz.

1. Java'da method ve classlar'da kullanılan final'ın C#'taki karşılığı sealed keyword'üdür.
2. Java'da fieldlarda kullanılan final'ın C#'taki karşılığı ise const (constant) veya readonly keywordleridir.

final veya sealed, bir method için belirtilmiş ise o methodun override edilmesini (ezilmesini), bir class için belirtilmişse başka bir class tarafından extend edilmesini (türetilmesini) engeller arkadaşlar. Bu kadar basit. Field'la beraber kullanıldığında ise o değişkenin değeri asla değiştirilemez, sabit kalır.

classlarda
java: public final class sampleClass{}
c#:   public sealed class sampleClass{}

methodlarda
java: public final void sampleMethod(){}
c#:   public sealed void sampleMethod(){}

fieldlarda
java: public final string name="Mustafa Güven" //asla başka bir değer ile değiştirilemez
c#:   public const string name="Mustafa Güven" //

17 Mayıs 2011 Salı

Boardwalk Empire !!!

Çocukluğumda bir dizi vardı. Cine 5, the simpsons ile birlikte sadece bu iki diziyi şifresiz verirdi. Bir gün simpsonlar'ın başlamasını beklerken şans eseri karşılaşmıştım ve o an ismini bile bilmediğim o dizi daha sonra müptelası olduğum ender dizilerin başında gelir oldu. Zaman geçti, büyüdük. Digiturk'te tekrar yayınlanmaya başladı. Hafta içi her gün gece 12'de başlar 1'de biterdi. Aşırı yoğun çalışıyor olsam da o diziyi izlemeden uyumazdım. O dizinin adı "OZ"'du.

Yine HBO yine aşmış bir yapım. Boardwalk Empire, OZ'da ne bulduysam izlediğim ilk anda işte bu elektrik çaktı kafamda. Abimin telefondaki gaz dolu sözleri sonrası öylesine indirdiğim birinci bölüm prodüksiyonun büyüklüğünü anlamamda yetti. Aslında fazla söze de gerek yok keza üç yapımcıdan biri Mark Wahlberg, ikincisi Martin Scorsese ve başrolde Steve Buscemi var. Hikayesi, karakterleri ve muhteşem oyunculuklarıyla gelmiş geçmiş en iyi dizi diyebilirim. 2. sezon'un 2011'de çıkacağı söylense de henüz hala beklemedeyiz. Bu diziyi kaçırmak büyük hata olur. Kesinlikle izleyin!


15 Mayıs 2011 Pazar

ZAZ

Mükemmel müzik, evet fransızlar bu işi biliyor. Sözlere baktığımda kafamdan sadece şu cümle geçti; bu şarkıyı ya bir Pendik'li yapabilirdi ya da bir Fransız. Tebrik ediyorum.
French
Je veux

Donnez-moi une suite au Ritz, je n'en veux pas
Des bijoux de chez Chanel, je n'en veux pas
Donnez-moi une limousine, j'en ferais quoi ?
Offrez-moi du personnel, j'en ferais quoi ?
Un manoir à Neufchatel, ce n'est pas pour moi
Offrez-moi la Tour Eiffel, j'en ferais quoi ?

Je veux de l'amour, de la joie, de la bonne humeur
Ce n'est pas votre argent qui fera mon bonheur
Moi je veux crever la main sur le coeur
Allons ensemble, découvrir ma liberté
Oubliez donc tous vos clichés
Bienvenue dans ma réalité

J'en ai marre de vos bonnes manières, c'est trop pour moi
Moi je mange avec les mains et je suis comme ça
Je parle fort et je suis franche, excusez-moi
Finie l'hypocrisie, moi je me casse de là
J'en ai marre des langues de bois
Regardez-moi, de toute manière je vous en veux pas et je suis comme ça !

Je veux de l'amour, de la joie, de la bonne humeur
Ce n'est pas votre argent qui fera mon bonheur
Moi je veux crever la main sur le coeur
Allons ensemble, découvrir ma liberté
Oubliez donc tous vos clichés
Bienvenue dans ma réalité

Türkçesi
İstiyorum

Ritz'de bir süt oda versen bana, istemem
Chanel'den mücevher, istemem
Bir limuzin versen bana, ne yaparım onunla ki?
Uşaklar teklif etsen bana, ne yaparım onlarla?
Neufchatel'de bir malikane, bana göre değil
Eiffel kulesini teklif etsen, ne yaparım onunla?

Aşk isterim, eğlence, iyi huy
Beni mutlu edecek olan paran değildir
Ölürken kalbimde bir el olsun istiyorum
Haydi birleşelim, özgürlüğümü keşfedelim
Tüm önyargını unut
Buyur benim gerçekliğime

İyi görgünden sıkıldım, bana çok fazla
Ben ellerimle yerim, ben böyleyim
Yüksek sesle konuşurum, dolaysızım
İkiyüzlülüğe son verelim, ben kurtuldum
Çifte konuşmalardan yoruldum
Bana bir bak, sana kızgın bile değilim, sadece ben böyleyim

Aşk isterim, eğlence, iyi huy
Beni mutlu edecek olan paran değildir
Ölürken kalbimde bir el olsun istiyorum
Haydi birleşelim, özgürlüğümü keşfedelim
Tüm önyargını unut
Buyur benim gerçekliğime