Mobil Uygulamalarda Analytic Event Pratikleri — 2

Mehmet Burak Akgün
Dolap Tech
Published in
3 min readOct 19, 2020

--

Merhabalar ,

Serinin devamı olarak ; kuyruğa ekleyerek event gönderimi gerçekleştirme , listede görüntülenen ürünlerin zaman ölçümlemelerini yapmak ve uyguladığımız diğer pratikleri aktaracağız. Android örnekler ve uygulamaya yer veriyoruz.

İlk partta bahsettiğimiz performans iyileştirmeleri ve doğru event gönderme pratiklerimizi okumadıysanız okumanızı öneriyoruz. İlk part için tıklayınız.

RecyclerView görüntülenlerin pozisyonu ve kaydırma olaylarını dinlemek

Event gönderim için kabul kriterimiz , ProductBox’un tamamının ekranda görünür olması şeklindeydi. Her kaydırma işlemi yapılırken görünen productBox’ların pozisyonlarını alabilmek için şu iki method’u kullanırız.

int findFirstCompletelyVisibleItemPosition()
int findLastCompletelyVisibleItemPosition()

RecyclerView kullanırken kaydırmaları algılamak için OnScrollListener eklememiz gerekir. Kaydırmaları ve ekranda görünmekte olan productBox’ları bir listener ile alabilirsiniz.

Ancak bu sınıf bize bir kullanıcının ekrandaki öğeye ne kadar süre baktığı ya da yeni görüntülenen ürün olduğu hakkında bilgi sağlamaz. Bu kısmı geliştirebilir ya da hazır çözümler kullanabiliriz.

Alternatif : RxJava ve Operatörler

Kullanıcı tarafından , UiThread’de kaydırma işlemleri yapılırken arkaplanda asenkron olarak veriyi filtreleyerek , pozisyon bilgisini işlememiz gerekiyor. Bunu memory leak gibi problemlere sebep vermeden halletmemiz tabii ki uygulamamızın faydasına olacaktır.

Eğer Coroutines kullanımı ile gerçekleştirmek isterseniz , 1.3.0'da stable olan Flow Api ile sağlamak yine bir çözüm olabilirdi.

Kullanıcının yaptığı kaydırma aksiyonlarını dinlerken , ekranda belirli bir süre için değişen item pozisyonlarını(product) tutmak ve view katmanına sunuş için RxJava’nın oldukça efektif olacağını düşünüyoruz.

Gereksinimleri karşılamak için kullandığımız filtre seti aşağıdadır:

  • distinctUntilChanged : reaktif bir şekilde ekranda kaydırma işlemi yapılırken , eşit pozisyon değerlerini atlamak için ,
  • throttleWithTimeout/debounce : gecikmeli bir olayı geçmek ve zaman aşımından önce başka bir olay gelirse mevcut olayı bırakmak için kullanıldı.

Burada tanımlanan kuralları view katmanından ayırmak için TrackingBus sınıfına koyduk. Bu sınıf Activity / Fragment’in içerisinde view oluşturulduktan sonra tanımlanmalı ve onStop() ‘da abonelikten(unSubscribe) çıkarılmalıdır.

onCallback içerisinde VisibleState class’ı bir önceki event için gönderilmiş olan pozisyonları tutmakta bu sayede mükerrer pozisyon bilgisinin gönderilmesini engelliyoruz.

data class VisibleState @JvmOverloads constructor(
val firstCompletelyVisible: Int = -1, val lastCompletelyVisible: Int = -1)

Buraya kadar productBox’lar için gönderilecek event’in doğru pozisyonda olmasını sağladık.

Her RecyclerView scroll eventi postViewEvent() methodunu çağırmaktadır. Bu method distinctUntilChanged methoduyla tekilliği garantilenmiş VisibleState bilgisine sahiptir. Bus 250 ms içerisinde birden fazla event’i yayınlamayacaktır. Bir önceki Event’ten farklılaşmış yeni event , onCallback() ile success methodunu çağıracaktır.

Success methodu ile onu tanımlayan Activity / Fragment’e geri dönen pozisyon bilgisi daha sonra networking işlemleri için WorkManager’a iletilir.

Neden WorkManager kullandık ?

Uygulama geliştiriciler için atılması gereken çok sayıdaki event / request’i bir anda atmak genelde tercih edilmez. Bunun yönetimi ve kurgunun başarılı çalısmasını sağlamaya çalışmak zor iştir.

Bizim event gönderirken beklentimiz ,

  • Sıralı bir şekilde gönderebilmek ,
  • Network State’ine göre göndermek ,
  • Uygulamanın açık olmasına ihtiyaç duyulmaması,
  • Cihaz kapanıp açılınca gönderime devam edebilmesi ve
  • Kolay bir şekilde Exponential backoff ekleyebilmek şeklinde sıralanabilir.
Credit: Working with WorkManager Presentation Android Developer Summit 2018

WorkManager bizim için gönderilmek istenen Event’leri kuyruğa ekleyip , teker teker(performans etkenini gözeterek), tanımlamış olduğumuz Constraint’e göre cihazın internet bağlantısı varsa gönderiyor ! Hatta bu işlem için uygulamanın açık olmasına gerek yok.

  • ExistingWorkPolicy.APPEND , işi kuyruğa ekler. FIFO geçerlidir.
  • OneTimeWorkRequest , recurring bir işlem olmayacağını belirtir.
  • Initial Delay , her Event’in gönderimi arasında ki bekleme süresini tayin eder.
  • NetworkType.CONNECTED , cihazın internet bağlantısının olması gerektiği kısıtıdır.

WorkManager tek seferlik işi enqueue ile kuyruğa ekledikten sonra belirtilen(EventWorker) worker sınıf , sırası geldiğinde bannerId parametresini AnalyticService’e network request’i için paslayacaktır.

Demo projenin tamamını görmek için GitHub’daki projemize göz atabilirsiniz.

Okuduğunuz için teşekkürler, soru ve fikirlerinizi yorumlara bekliyoruz. ✌️

Teknoloji ekibimize, birlikte güzel işler çıkartacağımız takım arkadaşları arıyoruz. Buradan iletişime geçebilirsiniz.

Dolap / Trendyol

--

--

Mehmet Burak Akgün
Dolap Tech

Senior Android Developer at Trendyol International @Berlin