13 Ekim 2017 Cuma

Temel RxJava (3)

Operatörler

Rxjava yı geleneksel java koduna göre bir adım öne geçiren olayın , yayınlanan datayı işlemek için çok geniş metod seti olduğundan ilk yazdımda bahsetmiştim . Bu yazımda bunlardan birkaçını açıklamaya çalışacağım .

flatMap()

Bir observable ın sonucunda oluşan değer tekrar başka bir observable a bağlanıyorsa . Yani asenkron bir işlem sonucu aslında başka bir asenkron işlem sonucuna bağlıysa içiçe iki tane observable yazmaktansa flatmap kullanılır .


Single.fromCallable(new Callable() {
            @Override
            public Integer call() throws Exception {
                return 1;
                //return 2;
            }
        }).flatMap(new Function>() {
            @Override
            public SingleSource apply(Integer integer) throws Exception {

                if (integer == 1)
                    return Single.just("fisrt");
                else
                    return Single.just("second");
            }
        }).subscribe(new Consumer() {
            @Override
            public void accept(String s) throws Exception {
                Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
            }
        });
Ekran Çıktısı : "first"
Örnekte ilk olarak Integer dönen bir observable oluşturulmuştur . Başka bir observable bunu dinlemektedir ve dönen sonuca göre String bir değer dönmektedir .

reduce()

Bir Observable birden çok değer üretiyor ve sonuc olarak bu değerlerin toplamı lazımsa reduce kullanılabilir .


  Observable.create(new ObservableOnSubscribe>() {
            @Override
            public void subscribe(ObservableEmitter> e) throws Exception {


                ArrayList strings = new ArrayList<>();
                strings.add("Hello");
                strings.add("Bro");
                e.onNext(strings);

                strings = new ArrayList<>();
                strings.add("Whats");
                strings.add("Up");
                e.onNext(strings);
                e.onComplete();

            }
        }).reduce(new BiFunction, List, List>() {
            @Override
            public List apply(List strings, List strings2) throws Exception {
                strings.addAll(strings2);
                return strings;
            }
        }).subscribe(new Consumer>() {
            @Override
            public void accept(List strings) throws Exception {
                Toast.makeText(MainActivity.this, strings.toString(), Toast.LENGTH_SHORT).show();
            }
        });

Ekran Çıktısı : [Hello,Bro,Whatsup,Kro]

onNext ile yayınlanan her "strings" listesi reduce methoduna girer ve orada parent strings e eklenir . Subsribe ise onComplete den sonra çalışır ve sonuç olarak iki onNext metoduyla yayınlanmış olan listelerin artarda eklenmiş halini alır .

Temel RxJava (2)

Observable - Single - Completable - Maybe

Bir önceki yazımda observable nedir nasıl kullanılırdan bahsetmiştim . Şimdi ise Observable yerine kullanılabilecek diğer dinleyici türlerine bir göz atalım .

Observable -> Birden fazla kez dinleyici tetiklenecek ise kullanılır . Bu yüzden onNext , onComplete adında iki methodu vardır . Her yayınlamada onNext tetiklenirken tüm akış bittiğinde ise onComplete tetiklenir .


Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {

                e.onNext("Hello");
                e.onNext("Ardahan");
                e.onComplete();

            }
        }).subscribe(new Observer() {
            @Override
            public void onSubscribe(Disposable d) {}

            @Override
            public void onNext(Object o) {
                Log.d(Tag, o);
            }

            @Override
            public void onError(Throwable e) {}

            @Override
            public void onComplete() {}
        });

Single -> Dinleyici sadece bir kez tetiklecek ise kullanılır . Bu yüzden onSuccess methodu mevcuttur .


Single.create(new SingleOnSubscribe() {
            @Override
            public void subscribe(SingleEmitter e) throws Exception {
                e.onSuccess("Hello");

            }
        }).subscribe(new SingleObserver() {
            @Override
            public void onSubscribe(Disposable d) {}

            @Override
            public void onSuccess(Object o) {
                Log.d(Tag, o);
            }

            @Override
            public void onError(Throwable e) {}
        });

Completable - > Single ile aynı gibi görünsede burada dinleyici tetiklenirken observable dan herhangi bir değer beklenmez . Arkaplanda bir işlem gerçekleştirilir ama sadece bitip bitmediğiyle ilgilenilir . 


Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter e) throws Exception {
                e.onComplete();
            }
        }).subscribe(new CompletableObserver() {
            @Override
            public void onSubscribe(Disposable d) {}

            @Override
            public void onComplete() {
                Log.d(Tag, "done");
            }

            @Override
            public void onError(Throwable e) {}
        });

Maybe -> Single ile Completable birleşimi gibidir . Hem onSuccess hem de onComplete methodları mevcut . Yani hiçbir sonuç dönmeyedebilir , tek bir sonuç dönedebilir .


Maybe.create(new MaybeOnSubscribe() {
            @Override
            public void subscribe(MaybeEmitter e) throws Exception {
                e.onSuccess("Hello");
               // e.onComplete();
            }
        }).subscribe(new MaybeObserver() {
            @Override
            public void onSubscribe(Disposable d) {}

            @Override
            public void onSuccess(String s) {
                Log.d(Tag, s);
            }

            @Override
            public void onError(Throwable e) {}

            @Override
            public void onComplete() {
                Log.d(Tag, "done");
            }
        });

Temel RxJava (1)

RxJava Nedir ?

RxJava (Reactive Extension) en temelde observable pattern üzerine kurulu asenkron işlemler için kullanılan güçlü bir kütüphanedir . Kendi içinde 3 parçaya ayrılır .

Observable (Gözlenen) - Observer (Gözlemci) - Datayı işleyen methodlar 

Observable = Datanın yayınlandığı yer
Observer = Datanın dinlendiği yer
Datayı İşleme = Data üzerinde filtreleme , ekleme , çıkarma vs.. işlemlerin yapıldığı yer

Observable.just(" Hello World ").map(new Function() {
            @Override
            public String apply(String s) throws Exception {
                return s.trim();
            }
        }).subscribe(new Consumer() {
            @Override
            public void accept(String s) throws Exception {
                Log.d("", s);
            }
        });


Ekran Çıktısı : HelloWorld

Yukarıdaki örnekte en basit haliyle bir örnek görebilirisiniz . "Hello World" yaylınlanıyor -> trim() ile filtreleniyor -> subscribe edilen yerde sonuç görüntüleniyor .

Neden RxJava Kullanmalıyım ?

Yukarıdaki örnekte bir string yayınlanmış onu da bir yerden dinlemiş basmışsın , bunun için mi yani bu rxjava diyebilirsiniz :) haklısınız . Peki ama neden neden kullanmalıyım diye sorarsanız !

(Java)


 new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                final List strings = new ArrayList<>();
                strings.add("Hello");

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, strings.toString(), Toast.LENGTH_SHORT).show();
                    }
                });


            }
        }).start();

Yapmak istediğim çok basit , bana bir liste dönecek olan bir işlem ama 500 milisaniyelik bir gecikme ile cevap veriyor . Cihazda UI kitlemeden arkaplanda bir işlem yapacağınızı düşünün ki bunu yapmak için yeni bir thread açmanız gerekiyor -Örnek amaçlı ben sonucu liste dönen bir işleme Thread.sleep(500) ile bir gecikme ekledim -. Ardından sonucu ekrana basacığınızı düşünün ki bunun içinde tekrar UI thread e geçmeniz yani bir runOnUiThread başlatmanız gerekiyor -Aksi takdirde exception alırsınız -.

Bunun yerine

(RxJava)

Observable.fromCallable(new Callable>() {
            @Override
            public List call() throws Exception {

                Thread.sleep(500);

                List strings = new ArrayList<>();
                strings.add("Hello");

                return strings;
            }
        }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer>() {
            @Override
            public void accept(List strings) throws Exception {
                Toast.makeText(MainActivity.this, strings.toString(), Toast.LENGTH_SHORT).show();
            }
        });


ObserveOn = Subsriber hangi threadde çalışması dinlemesi gerektiğini belirtiyoruz . -AndroidSchedulers.mainThread() yani main threadde dinle . -
SubscribeOn = Observable sonucu yayınlanacak olacak işlemin hangi threadde çalışması gerektiğini belirtiyoruz . -Ben newThread() kullandım ama Schedulers.io da aynı işi yapıyor sadece var olan ama boşa çıkmış threadlerden birini kullanıyor .-

Bunlara ek olarak RxJava ile data üzerinde işlem yapabileceğiniz çok güçlü bir method set (Operators) olduğunu hesaba katarsak . RxJava geleneksel java koduna göre daha baskın geliyor .


Makalenin devamını linkten bulabilirisniz

23 Nisan 2017 Pazar

Data Binding

Android uygulama geliştirirken UI ile java sınıflarını birbirine bağlamanın en sıkıcı işlerden biri olduğu bilinir . Bu sebeptendir ki bu amaçla kullanılan Butterknife şu android geliştiricileri arasında en popüler kütüphanlerden biri haline geldi . Son zamanlarda sıkıntıyı farketmiş olucaklar ki Google/IO 2015 te yeni data binding support library i tanıttı . Bu kütüphane sayesinde itemlerinizi tek tek  arayüzden findByViewId ile yakalayıp ardından onları cast edip -hataya gayet açık yöntemler- ardından onlara tek tekmodelinizdeki ilgili parametreleri doldurmak gibi zahmetli bir işten kurtulabilirsiniz . Kullanımı gayet basit tutulan kütüphanenin örneğini sayfanın en altındaki linkten bulabilirsiniz .

STEP 1 (Temel)
İlk olarak kütüphaneyi kullanabilmeniz için build.gradle dosyanızdan dataBinding i aktif hale getirmeniz yeterli . "Gradle version minimum 1.5.0 olmalı !"

...android {
compileSdkVersion ...
buildToolsVersion ...
defaultConfig {...}
dataBinding { enabled = true }
 ...
} 

Kullancağınız layout dosyalarında ise dikkat etmeniz gereken ilk şey "<layout>" tag' ile başlayıp derleyiciye bu dosyayı bind etmesi gerektiğini belirtmektir.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout 
  android:layout_width="match_parent" 
  android:layout_height="match_parent">
 
     <TextView android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

</RelativeLayout>
</layout>

Tebrikler artık findByViewId methodundan kurtuldunuz . Bu dosyadaki itemlerinizi direk activity sınıfınızdan kullanabilirsiniz .

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView( this, R.layout.activity_main);
activityMainBinding.text.setText("Hello World Test"); }
STEP 2(Arayüze Müdahale)
Android binding library yukarıda da görüldüğü gibi ilk etapta findByViewId ile araryüzü activity e bağlama zorunluluğunu ortadan kaldırmıştır . Tabi sadece bununla sınırlı olmayan kütüphane ile modellerinizi de bu arayüz itemlerine zahmetsiz init edebilirsiniz .

Bunun için ilk yapmanız gereken layout dosyanızda kullancağınız model i "<data>" tag i içerinde belirtmek .

<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
      <variable 
           name="testModel"
           type="com.example.databinding.Test" />
  </data>

<RelativeLayout 
   android:layout_width="match_parent" 
   android:layout_height="match_parent"> 
<TextView 
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="@{testModel.textStr}" />

 </RelativeLayout> 
</layout>
Örnekte kullanılacak olan TestModel i sadece textStr adında bir string içeren basit bir pojo modeli olarak düşünebilirsiniz . TextView altında bulunan android:text="@{testModel.textStr}" tagi bu textview a modeldeki textStr nin doldurulacağı anlamına gelir . Artık tek yapmanız gereken activity sınıfınızdan arayüze modelinizi setlemek .

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(
                this, R.layout.activity_main);
        Test test = new Test("Hello World Test 2");
        activityMainBinding.setTestModel(test);
    }
Kullanımı gayet basit tutulan kütüphanenin örneğini linkten bulabilirsiniz . -Picasso ile image nasıl eklenir , layout a logic nasıl yazılır linkte mevcut -

7 Ocak 2017 Cumartesi

Otto - Android EventBus

Yazılım geliştirirken en dikkat edilmesi gereken konulardan biri loose coupling yani esnek bağlı tasarım . Fakat ne kadar bağımlılıktan kaçınsanızda çoğu yerde activityler fragmentlarla servislerle veya activityler diğer activiylerle haberleşmesi gerekebilir . Bu bahsettiklerim geleneksel olarak interfacelerle yapılabilir -Bir sınıfta instance , bir sınıfta ilgili methodlar kullanılarak haberleşebilirler-. Burda karşılaşılabilen en büyük handikap kullanılmayan methodlarında çoğu classda bulunarak gereksiz yer kaplaması veya sürekli bir üst sınıfa taşınması gereken instance lar. . İkinci yöntem ise eventbus kütüphanesi . Otto ise bu eventbus kütüphaneleri arasındaki en bilinenlerden biri . Temel olarak yapmanız gereken 5 aşama var .

1) Otto sınıfının heryerden ulaşılabilecek bir constructorı oluşturulur .
 2) Kullanılacak olan sınıfa register edilir .(kayıt edilir)
3) Mesaj tipi oluşturulur .
 4) Mesaj tipine subscribe olunur .
 5) Mesaj gönderilir - yakalanır. Şimdi sırayla açıklayalım .

1) Otto sınıfının heryerden ulaşılabilecek bir constructorı oluşturulur . Bunu yapmanın en kolay yolu bir tane application sınıfı açılır ve içinde static bir nesne oluşturulur .

public class ApplicationClass extends android.app.Application {
            public static Bus busProvider;

            @Override
            public void onCreate() {
                super.onCreate();
                busProvider = new Bus();
            }
        }

2) Kullanılacak olan sınıflar register edilir -kayıt edilir-.(hem mesajı gönderecek hem yakalayacak kısım ).

 public class MainActivity extends AppCompatActivity {
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ApplicationClass.busProvider.register(this);
            }

3) Mesaj tipi oluşturulur . (Bir sınıftan diğerine bir String nesnesi taşınacak)

public class Message {
            public String count;

            public Message(String count) {
                this.count = count;
            }
        }

4) Mesaj tipine subscribe olunur . (Gelecek mesajın yakalandığı yer)

@Subscribe void callingMessage (Message message){
            message.count;
        }

5)Mesaj gönderilir. (Senkron olarak o an register olan sınıftaki method tetiklenir )

plus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ApplicationClass.busProvider.post(new Message("plus"));
            }

 İlgili örneği linkten bulabilirsiniz