Android Studio ile RxJava/RxAndroid Kullanımı

Android Programlama iş ilanlarında da sıklıkla ismi geçen; RxJava/RxAndroid kavramları ile alakalı küçük bir makale yazırlama ihtiyacı duydum. Aslında RxJava ve RxAndroid birbirinden bağımsız konular değildir.

Android Mobil Uygulama geliştirirken Main Thread üzerinde işlem gerçekleştirmeye çalıştığımızda, örneğin bir web sayfasının içeriğini doğrudan String olarak elde etmek istediğimizde ilgili web sayfasına doğrudan bağlanıp içeriği çekmeye çalışırsanız, android.os.NetworkOnMainThreadException hatası ile karşılaşabilirsiniz.

Örneğin bu hatayı alabilmek için test edebileceğiniz kodlar şöyledir;

try {
InputStream is = new URL("https://serifgungor.com").openStream();
Scanner sc = new Scanner(is);
StringBuffer sb = new StringBuffer();
while(sc.hasNext()){
sb.append(sc.nextLine());
}
Log.d("JSON", sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Bu hatayı alma sebebiniz doğrudan web sayfasına bağlanıp, o esnada içeriği okuyamayacağı içindir. Bu hatayı almamak için web sitede bulunan veriyi AsyncTask sınıfının doInBackground metodu ile çekebilirsiniz.

new AsyncTask<String,String,String>(){
@Override
protected String doInBackground(String... strings) {
StringBuffer sb = new StringBuffer();
try {
InputStream is = new URL("https://github.com").openStream();
Scanner sc = new Scanner(is);
while(sc.hasNext()){
sb.append(sc.nextLine());
}
Log.d("JSON", sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return sb.toString();
}
}.execute();

AsyncTask sınıfının doInBackground metodu verileri parça parça çekerek değişkende saklayacağından dolayı problem çıkarmayacaktır. Geliştirici olarak her zaman AsyncTask kullanmak durumunda kalmayız, hele ki bir veriyi web sayfası üzerinden çekmek gerekirse. AsyncTask yerine zaten Volley veya Retrofit kütüphanelerini kullanabiliyoruz. AsyncTask yerine farklı bir yapı kullanmayı düşündüğünüz zamanlar oluşabilir.

- Çoklu Web Servis isteklerinde gecikme/kısıtlama

- Bellekte bağımsız referanslarda iki ayrı AsyncTask nesnesi üretmek, tek nesne üzerinden ilerlemekten daha iyi sonuç veriyor.

- Hata olduğunda hatayı yakalayamıyoruz. Bu nedenle bir işlemi tetikleyemiyoruz.

RxJava projemize nasıl tanımlanabilir;

- Projemizin build.gradle(Module: app) içerisindeki android scope'u içerisine

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

ve depentencies scope'u içerisine ise;

implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'

ekleyiniz. build.gradle(Project) olan dosyamıza ise repositories scope'larına;

maven { url "https://oss.jfrog.org/libs-snapshot" }
ilave ediniz.

RxJava ile Hata yakalama işlemi şöyle tanımlanmaktadır;

Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception { //isteğin gönderilmesi
return null;
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Throwable {
//sonuç döndürülmesi
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Throwable {
//hatanın yakalanması
}
} );

AsyncTask sınıfının onPreExecute,doInBackground ve onPostExecute metotları sayesinde UI arayüzüne veri iletimi sağlayabilmekteyiz. Örnek verecek olursak

new AsyncTask<String,String,String>(){
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
@Override
protected void onPreExecute() {
super.onPreExecute();
//işlem başlamadan önce
progressDialog.setTitle("Başlık");
progressDialog.create();
progressDialog.show();
}

@Override
protected String doInBackground(String... strings) {
SystemClock.sleep(5000);
return null;
//işlemin gerçekleştirilme zamanında
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressDialog.dismiss();
//işlem tamamlandığında
}
}.execute();

Aynı işlemi AsyncTask kullanmak yerine RxJava ile de gerçekleştirebilirsiniz.

public class MainActivity extends AppCompatActivity {

ProgressDialog progressDialog;
public void islemYap(int beklemeSuresi) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Başlık");
progressDialog.create();
progressDialog.show();
Observable.fromCallable(() -> {
//işlem başladığında
SystemClock.sleep(beklemeSuresi);
return false;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((result) -> {
progressDialog.dismiss();
//işlem bitmeden önce
});
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
islemYap(5000);
}
}

RxJava'nın birçok farklı kullanımı mevcuttur. AsyncTask ile çözemediğiniz durumlarda tercih edilebilir bir yapı olduğunu unutmayalım. RxJava, AsyncTask sınıfına göre daha kullanışlı ve esnektir.

Observable.fromCallable(new Callable<String[]>() {
@Override
public String[] call() throws Exception {
String[] strings = new String[]{"Hey", "You", "Win !"};
return strings;
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<String[]>() {
@Override
public void accept(String[] t) throws Throwable {
for (int i = 0; i < t.length; i++) {
SystemClock.sleep(2000);
Toast.makeText(MainActivity.this, t[i], Toast.LENGTH_SHORT).show();
}

}
});

Bu kullanımda ise kodların tamamen Hey, You,Win gibi yazıları her 2 saniyede 1 çıktı göstermesini beklersiniz. Ama öyle değil, accept metodu, call metodundan gelen tüm değerleri kabul eder. for döngüsünde bütün elemanları tek tek gez hepsini ekrana yazdır dememize rağmen, bütün elemanlar için 2 sn bekleyip, son elemanı yazıp metottan çıkıyor.

Yine incelediğim güzel bir anlatım olan https://medium.com/kocsistem/temel-rxjava-1-730013735858 makalesinden de faydalanabilirsiniz.

Vakit bulabildikçe araştırıp yeni içerikleri, makale olarak tekrar ele almaya çalışacağım.

Keyifli çalışmalar.

Bu makaleyi paylaşın:

Toplam yorum sayısı: 0

Bir yorum bırakın