COMPANION OBJECT---------------------------------------------------------
kotlin'de static properties ve static fonksiyonlar oluşmasına izin verilmez.
Java'da verilirdi. Bunun için "Companion Object" kavramı kullanılır.
Companion Object içerisinde sınıfta static olmasını istediğimiz Constants,
Properties, Functions tanımlayıp rahatça kullanabiliriz.
class Foo {
public static Foo instance;
public Foo() {
instance = this;
}
}
-javada bu şekilde olan metod, kotlinde şu şekilde tanımlanır:
class Foo {
companion object {
lateinit var instance: Foo
}
init {
instance = this
}
}
Class’ı tekil(singleton) halde kullanabilmeyi sağlamak için companion
object'i kullanırız.
class Car(val horsepowers: Int) {
companion object Factory {
val cars = mutableListOf()
fun makeCar(horsepowers: Int): Car {
val car = Car(horsepowers)
cars.add(car)
return car
}
}
}
Companion Object tek bir nesnedir ve üyelerine, içerdiği sınıfın adı
aracılığıyla doğrudan erişebiliyoruz.
val car = Car.makeCar(150)
println(Car.Factory.cars.size)
Kısaca Companion Object’i şu şekilde aklımıza kazıyabiliriz :
Companion Object içinde tanımlı olan nesneler başka programlama dillerindeki
(Java, C#) statik üyelere benzemektedir. Aslında Companion Object çalışma
zamanında gerçek nesnelerin üyeleridir ve bu nedenle bir Interface’i
realized ederken bile kullanabiliyoruz.
----------------------------------------------------------------------------
-> coroutineler kullanılacağı zaman suspend fonksiyon kullanılır.
-> ya da Scope.launch{} ile courutine scop'u oluşturulup kodlar yazıalbilir.
-------------------------------------------------------------------------
state'ler değişiklik olduğunda recompose için gereklidir.
-------------------------------------------------------------------------
Flows -> livedata yerine kullanılıyor.
Coroutinler içinde çalışıyorlar. multiple değer emit'leyebilen(yayabilen)
yapılardır. suspend'de tek döndürebiliyoruz. veri tabanından canlı güncelle-
meler alıp kullanabiliyoruz örneğin. javada yok, kotlinde var.
retrofitle veri çekerken flow kullanılabilir.
livedata-flow farkı ne?
hemen hemen aynı eşyleri yapabiliyoruz ama flow biraz daha kullanım alanı
geniş.
flow operatörler gibi...
flow operatörleri: map, filter, collect...
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
flowların türleri vardır.
stateflow, sharedflow gibi...
stateflow da bir sharedflowdur. sharedflowu alıp kendimiz konfigüre ederiz.
böyle bir yapıdır. böyle bir şeye gerek yoksa stateflow ya da flow kullanıla
bilir.sharedflow kullanılacaksa inital bir değer verilmeldir.
https://developer.android.com/kotlin/flow/stateflow-and-sharedflow
-StateFlow, uygulamanız arka plandayken aktif kalacaktır, ancak küçük bir
kurulumla LiveData'yı StateFlow olarak yapabilirsiniz.
-stateflow initial değerinin olmasına ihtiyaç duyar, live data ise
duymaz, opsiyoneldir.
-eğer bir initial(yani başlangıç) değeri varsa stateflow kullanmak daha
doğrudur.
-Stateflow ile Flow operatörlerini kullanabilirsiniz ve bu LiveData ile
yapamayacağınız bir şeydir, LiveData'yı Flow ile kullanmak istiyorsanız
daha fazlasına ihtiyacınız vardır.
-------------------------------------------------------------------
init{} metodu classın özelliklerini alır(contructor gibi ama biraz farklı).
init bloğu, primary constructor'dan hemen sonra yürütülür.
initilazer blokları etkin bir şekilde primary constructor'ın bir parçası
haline gelir. constructor secondary constructor'dır. primary constructor'a
delegasyon,
secondary constructor bir kurucunun ilk ifadesi olarak gerçekleşir, bu
nedenle tüm başlatıcı bloklarındaki kod, ikincil kurucu gövdesinden önce
yürütülür.
class Sample(private var s : String) {
constructor(t: String, u: String) : this(t) {
this.s += u
}
init {
s += "B"
}
}
Sample("T","U")
çıktı: "TBU". önce init, sonra constructor çağırıldı, aralarıdnaki fark bu.
T primary constructor(görmüyoruz) olduğu için en önce o çağırıldı.
https://www.geeksforgeeks.org/how-to-initialize-constructor-in-kotlin/
-> bir classta birden fazla init bloğu kullanabiliriz ama tek bir tane
kullanılarsa daha iyi olur.
---------------------------------------------------------------------
jetpack'daki lazyColumn kotlin ve javadaki recyclerView'dır.
----------------------------------------------------------------------
compose'da side effects:
uygulamanın state'inde değişiklik yapan ama aynı zamanda composoble
scopeunun dışında olan şeyler. böyle bir durumda loopa girme gibi hatalar
olabiliyor.recomposition'a yok açarak, sürekli baştan açma durumunda buglar
meydana gelir.
sorunu çözmek için LaunchedEffect kullanılabilir. launchEffect sayesinde
sadece bir defa istek gönderildiğini anlar ve böyle arkada sürekli istek
gönderme, yani loop durumu meydana gelmez.
LaunchedEffect(key1 = Unit){ //this: CoroutineScope
bla bla...
}
produceState de bu sorunu çözer.
produceState non-compose state'leri compose statelere çevirir.
val x = produceState(initialValue = ""){ //this: ProduceState
value = x bla bla...
}
DisposableEffect -> callbacklerle önceki verileri kaldırma gibi işler yapar.
böylelikle bahsedilen looplardan kurtulmuş olunur.
bu effectleri ele alma biçimine effect handlers denir.
--------------------------------------------------------------------------
coroutine:
Bir ağ isteği attığımızda, local databaseden bir veri isteği yaptığımızda
veya daha genel olarak threadde uzun sürecek bir işlem yaptığımızda
imdadımıza main threadi kitlememek ve kesintisiz akışı kesmemek için
coroutineler yetişiyor. Coroutinesleri threadde yapılan işlemin yapıldığı
iş parçacıkları olarak düşünebiliriz.Genel olarak Lightweight Thread olarak
tanımlanıyor. Bu konuda şuraya özellikle vurgu yapmak istiyorum; Threadlere
benzer olmalarına rağmen coroutinesleri kullanarak yeni bir threadde iş
yapmış olmuyoruz. Zaten coroutineslerin bu kadar popüler yapanda o. Çünkü
yeni bir thread açmak çok maliyetli bir işlem. Out of memory hatası
almamıza yol açabilir. Fakat coroutinesler threadlere göre çok daha light
yapılar olduğu için daha az enerji harcayarak daha çok iş yaparlar.
Yani Mevcut threadi bloklamadan askıya alınma işlevini sağlarlar.
suspend
Suspend Fonksiyonlar, normal bir fonksiyon yazmak gibidirler.
Tek farkı sadece suspend keywordu getirilerek başlatırlar. İçerisinde
coroutines çalıştırılabilen fonksiyonlardır. İstediğimiz zaman durdurup,
devam ettirip ve bitirebiliriz. Burada dikkat edilmesi gereken nokta
suspend fonksiyonları ya bir suspend fonksiyon içerisinden veya coroutine
içerisinden çağırabiliriz.
suspend fun introduceYourself(){
delay(2000)
coroutineScope {
launch {
println("Merhaba ben suspend fonksiyonum.")
}
}
}
Coroutine Dispatchers
Coroutinelerimizi farklı threadlerde çalıştırmayı sağlar. Yapacağımız
işlemin niteliğine göre dispatchersla hangi threadde olacağını belirteceğiz.
Dispatchers.Default : CPU kullanımın yoğun olduğu işlerde kullanılır.
Örneğin görüntü işleme gibi ya da çok uzun bir dizinin içinden bir
filtreleme yapmak gibi işlerde kullanılır.
Dispatchers.IO : Networking işlemlerinde kullanılır. Örneğin internetten bir
veri çekmek veya databaseden veri almak gibi işlemlerde kullanılır.
Dispatchers.Main : UI ile ilgili yaptığımız işlemler için kullanılır.
Örneğin IO’da yaptığımız bir işi mainle gösterebiliriz. İnternetten veri
çekerekn IO’yu, bu veriyi kullanıcıya UI’da gösterirken Main’i
kullanabiliriz.
----------------------------------------------------------------------------
Sealed Class(mühürlü sınıflar)
-türetilemezler(çünkü soyutlardır).
-Enum classların daha gelişmiş halleridir
Nesneye dayalı programlama yaklaşımında kalıtım (inheritence) özelliği
sayesinde bir sınıftan başka sınıflar türetilebilir ve bu sınıflara yeni
özellikler eklenerek daha zengin ve kullanışlı sınıflar yaratılabilir.
Ancak bazı durumlarda sınıflardan türetme yapılması istenmez. Bu durumda
sınıf tanımlamasının başına mühürlü (sealed) kelimesi getirilir. Bu sayede
sabit özellikler ve metotlara sahip bir sınıf elde edilir. Mühürlü
sınıf (sealed class) hiçbir sınıfın kendisinden türetilemeyeceğini ifade
eder.
Türeyen sınıfın anlamsız olmasının engellenmesi, bazı üyelerin güvenliğinin
sağlanması ya da üyeleri statik olan sınıfların korunması amacıyla
türetilme yapılmaması için sealed (mühürlü) anahtar kelimesi kullanılarak
mühürlü sınıflar (sealed class) oluşturulur.
Enumlarda parametresiz çağırma gerçekleşemez. Enumlar tek tür veri
tipi tutabilir. Ayrıca Enumlarda parametre varsa tüm değerler oluşturma
anında set edilmeli, bu durum da kapsülleme yaparken ihtiyacımız dışındaki
alanların set edilmesini zorunlu kılıyor. bu da clean code açısından doğru
değil. Sealed class'ta ise bu bir problem olmaktan çıkıyor.
-Çünkü Enumlar tek bir değişken tipi tutabiliyorken Sealed Sınıflar her
bir state için farklı değişken tipi tutabilirler.
---------------------------------------------------------------------------
Data Class
Data Class’lar verileri depolamak için kullanılan özel sınıflardır ve
data anahtar sözcüğüyle tanımlanırlar. Data Class’larda getter ve setter
metotları, hashCode(), equals(), toString(), copy() metotlarını
kendiliğinden üretir.
Enum Class
Kullanıcı tarafından tanımlanan veri kümeleri için enum class‘lar
kullanılabilir
Singleton Class(object ya da companion object)
Singleton class singleton nesnesi olarak da adlandırılabilir.
Bir sınıftan "yalnızca bir örnek" oluşturmak ve bunu bu haliyle her yerde
kullanmak istediğimizde bu yolu izleyebiliriz. Class anahtar sözcüğü yerine
object anahtar sözcüğünü kullanırız.
object Calculate {
fun multiplying(number1: Int, number2: Int): Int {
return number1 * number2
}
}
---------------------------------------------------------------------------
DataStore
Shared Preferences(deprecated ama androidx kütüphanesiyle kullanılabilir,
android documanda geleneksel olarak hala öneriliyor.) yerine kullanılabilir. 2 adet dataStore var. Preference DataStore ve
proto dataStore. bu ikisi çok benzer ama ufak farklılıkları var.
preference datastore -> proto gibi type safe değildir.
proto datastore -> type safe'dir. biraz komplekstir.
setup kurmak ve basit verileri kaydetmek için model kurmak gerekir.
bu yüzden bunu kullanmak(type safe'e ihtiyaç varsa özellikle) yerine room
kullanmak daha iyi bir fikir olabilir.
----------------------------------------------------------------------------
Type Safety
Type-Safety, “tür güvenliği” olarak çevirilebilir. yazılımda kullanılan bir
terimdir. Tür güvenliği, derleyici derleme sırasında türleri doğrulayacak
ve biz bir değişkene yanlış tür atamayı denersek hata vereceği anlamına
gelir. Örneğin C#, C++, Java type-safe bir dildir. Java’da bir değişken
tanımlamak istediğimizde o değişkenin hangi veri tipinde bir değişken
olduğunu belirtmek zorundayız. Mesela PHP, JavaScript ve diğer dynamic
scripting dillerinde bu durum söz konusu değildir. JavaScript’de bir
değişken tanımladığımızda bu değişkenlere bir tip atamak zorunda değiliz,
yani bir seferinde o değişkene sayı atayıp sonrasında aynı değişkene
karakter atayabiliriz.
----------------------------------------------------------------------------
instance
Kısaca nesne denebilir.
Bir evin tasarım planı,bir sınıfı ifade etsin(Class). Bu plandan inşa edilen
tüm evler, bu sınıfın nesneleridir(Object). Ve her bir ev de birer
örnektir(Instance).
----------------------------------------------------------------------------
Dependency Injection
-dagger/hilt
aslında bir tür design pattern'dır. bu patternin amacı verilen bir objenin
variable'larının instance edilmesidir.
-Hilt kullanan tüm uygulamalar, @HiltAndroidApp annotasyonu içeren bir
Application sınıfı içermelidir.
@HiltAndroidApp
class ExampleApplication : Application() { ... }
Bu oluşturulan Hilt bileşeni, Application nesnesinin yaşam döngüsüne eklenir
ve ona bağımlılıklar sağlar. Ek olarak, uygulamanın ana bileşenidir; bu,
diğer bileşenlerin sağladığı bağımlılıklara erişebileceği anlamına gelir.
Android sınıflarına bağımlılıkları enjekte etme:
-Hilt, Application sınıfınızda ayarlandığında ve uygulama düzeyinde bir
bileşen kullanılabilir olduğunda Hilt, @AndroidEntryPoint ek annotasyonuna
sahip diğer Android sınıflarına bağımlılıklar sağlayabilir:
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { ... }
Hilt aşağıdaki Android sınıflarını desteklemektedir:
Application (by using @HiltAndroidApp)
ViewModel (by using @HiltViewModel)
Activity
Fragment
View
Service
BroadcastReceiver
@AndroidEntryPoint ile bir Android sınıfına açıklama eklerseniz, buna bağlı
olan Android sınıflarına da açıklama eklemeniz gerekir. Örneğin, bir parçaya
açıklama eklerseniz, o parçayı kullandığınız tüm aktivitelere de de açıklama
eklemelisiniz.
-Bir bileşenden bağımlılıklar elde etmek için, alan(field) enjeksiyonu
gerçekleştirmek için @Inject ek açıklamasını kullanın:
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
@Inject lateinit var analytics: AnalyticsAdapter
...
}
Hilt'in enjekte ettiği sınıflar, enjeksiyon kullanan başka temel
sınıflara da sahip olabilir. Bu sınıflar, soyutlarsa @AndroidEntryPoint
ek açıklamasına ihtiyaç duymazlar.
Hilt bağlamları tanımlama(bindings):
Alan(field) enjeksiyonunu gerçekleştirmek için Hilt'in ilgili bileşenden
gerekli bağımlılıkların örneklerini nasıl sağlayacağını bilmesi gerekir.
binding, bir türün örneklerini bir bağımlılık olarak sağlamak için gerekli
bilgileri içerir. Hilt'e bağlama bilgisi sağlamanın bir yolu, constructor
enjeksiyonudur. Hilt'e o sınıfın örneklerini nasıl sağlayacağını söylemek
için bir sınıfın yapıcısında @Inject ek açıklaması kullanılır.
class AnalyticsAdapter @Inject constructor(
private val service: AnalyticsService
) { ... }
Hilt modüller:
Bazen belli sebeplerden dolayı constructor injected yapamayız. Mesela bir
interface'e constructor enjekte edemeyiz. ya da dışarıdan bir kütüphaneye
constructor ekleyemeyiz. böyle durumlarda hilt modülleri kullanılır.
Hilt modülü, @Module ile açıklamalı bir sınıftır. Bir Dagger modülü gibi,
Hilt'e belirli türlerin örneklerinin nasıl sağlanacağını bildirir. Dagger
modüllerinden farklı olarak, Hilt'e her modülün hangi Android sınıfında
kullanılacağını veya kurulacağını söylemek için Hilt modüllerine @InstallIn
ile açıklama eklemelisiniz.
Hilt modüllerinde sağladığınız bağımlılıklar, Hilt modülünü kurduğunuz
Android sınıfı ile ilişkilendirilmiş oluşturulan tüm bileşenlerden
ulaşılabilir
Inject interface instances with @Binds:
sınıfınız bir arayüzse, onu constructor-enjekte edemezsiniz. Bunun yerine,
Hilt modülü içinde @Binds ile açıklamalı soyut(abstract) bir işlev
oluşturarak Hilt'e bağlama bilgilerini sağlayın.
interface AnalyticsService {
fun analyticsMethods()
}
// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(
...
) : AnalyticsService { ... }
@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {
@Binds
abstract fun bindAnalyticsService(
analyticsServiceImpl: AnalyticsServiceImpl
): AnalyticsService
}
@Provides ile instanceları enjekte etme:
Bir türü contructor enjekte edemediğiniz tek durum arayüzler değildir.
Sınıfın harici bir kitaplıktan retrofit, OkHttpClient veya Room veritabanları
gibi sınıflar) geldiği için sınıfın sahibi değilseniz veya builder
modeliyle örneklerin oluşturulması gerekiyorsa, constructor ekleme de mümkün
değildir. Önceki örneği düşünün. AnalyticsService sınıfına doğrudan sahip
değilseniz, Hilt modülü içinde bir işlev oluşturarak ve bu işleve
@Provides ile açıklama ekleyerek Hilt'e bu tür örneklerin nasıl
sağlanacağını söyleyebilirsiniz.
annotasyonlu fonksiyon Hilt'e aşağıdaki bilgileri sağlar:
-fonksiyon return türü, Hilt'e fonksiyonun hangi türün nesnelerini
sağladığını(provide ettiğini) söyler.
-fonksiyon parametreleri Hilt'e karşılık gelen türün bağımlılıklarını söyler.
-fonksiyon gövdesi, Hilt'e ilgili tipte bir instancesın nasıl sağlanacağını
söyler. Hilt, bu türden bir instance sağlaması gerektiğinde fonksiyon
gövdesini yürütür.
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {
@Provides
fun provideAnalyticsService(
// Potential dependencies of this type
): AnalyticsService {
return Retrofit.Builder()
.baseUrl("https://example.com")
.build()
.create(AnalyticsService::class.java)
}
}
Hilt component --- Injector for
SingletonComponent Application
ActivityRetainedComponent N/A
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View annotated with @WithFragmentBindings
ServiceComponent Service
Component lifetimes
Hilt, ilgili Android sınıflarının yaşam döngüsünü takiben oluşturulan
bileşen sınıflarının instanceları otomatik olarak oluşturur ve yok eder.
Generated component Created at Destroyed at
SingletonComponent Application#onCreate() Application destroyed
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel created ViewModel destroyed
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() View destroyed
ViewWithFragmentComponent View#super() View destroyed
ServiceComponent Service#onCreate() Service#onDestroy()
https://developer.android.com/training/dependency-injection/hilt-android#kotlin
----------------------------------------------------------------------------
Kotlin generics
Jenerikler, derleme zamanı tipi güvenliğini kontrol ederken farklı veri
türleri kullanılarak erişilebilen sınıfları, yöntemleri ve özellikleri
tanımlamamıza izin veren güçlü özelliklerdir.
Parametreli sınıflar oluşturma:
Genel bir tür, türler üzerinde parametrelendirilen bir sınıf veya yöntemdir.
Programda type parametresini belirtmek için her zaman köşeli parantez ()
kullanırız.
class MyClass(text: T) {
var name = text
}
Böyle bir sınıfın bir instancesını/nesnesi oluşturmak için, tür argümanlarını
sağlamamız(provide etmemiz) gerekir:
val my : MyClass = Myclass("GeeksforGeeks")
Parametreler constructor argümanlarından çıkarılabiliyorsa, tür
argümanlarının atlanmasına izin verilir:
val my = MyClass("GeeksforGeeks")
Jenerik avantajları:
–Type casting'den kaçılabilir. - Nesneyi type cast etmeye gerek yoktur.
-Type safety - generic, bir seferde yalnızca tek tip nesneye izin verir.
-Derleme zamanı güvenliği - generic kod, çalıştırma zamanı hatasını önlemek
için parametreli tür için derleme zamanında kontrol edilir.
genericsiz kotlin:
class Company (text: String) {
var x = text
init{
println(x)
}
}
fun main(args: Array){
var name: Company = Company("GeeksforGeeks")
var rank: Company = Company(12)// compile time error
}
hata mesajı:
Error:(10, 33) Kotlin: The integer literal does not conform to the expected type String
generic kullanılarak:
class Company (text : T){
var x = text
init{
println(x)
}
}
fun main(args: Array){
var name: Company = Company("GeeksforGeeks")
var rank: Company = Company(12)
}
çıktı:
GeeksforGeeks
1234
----------------------------------------------------------------------------
java ya da kotlinde app farklı dil seçeneklerine sahip olacaksa farklı
strings.xml dosyaları açılır. strings.xml, strings.xml (de) gibi(almanca..).
Hallo Welt
bu kadar. almanca olduğu zaman almanca strings içerisindeki hallo_world
değişkeninin değeri Hallo Welt olacak. Bu yüzden yazıları strings.xml'de
tutmak lazım,öküz gibi sınıfların içine yazmamak lazım çeviri ihtiyacı varsa.
Ayrıca örneğin compose'da;
Text(text = stringResource(id = R.string.hello_world))
yazarak yanda çıkan uyarıya tıklayabilirsin. Böyle bir strings dosyası yok,
yaratayım mı diye sorar. Strings dosyasını kendin oluşturup içini doldurmana
gerek yok.
----------------------------------------------------------------------------
Dizi vs ArrayList
1.)
Dizi, dizi nesnesi oluşturulduktan sonra uzunluğu değiştirilemeyen sabit
uzunluklu bir veri yapısıdır.
ArrayList doğada dinamiktir, bu da gerektiğinde büyümesi için yeniden
boyutlandırılabileceği anlamına gelir.
2.)
Bir dizinin boyutu program boyunca sabit kalır.
ArrayList'in boyutu yüke ve kapasiteye bağlı olarak dinamik olarak
büyüyebilir.
3.)
dizide Öğeleri depolamak için atama işleci kullanır.
arraylistte Öğeleri eklemek için add () özelliğini kullanır.
4.)
Aynı veya farklı veri türündeki nesnelerin yanı sıra ilkel öğeler içerebilir.
ArrayList'te temel öğelere izin verilmez. Yalnızca nesne türlerini içerebilir.
5.)
Diziler ve Jenerikler el ele gitmez.
ArrayList'te jeneriklere izin verilir.
6.)
Diziler çok boyutlu olabilir.
ArrayList tek boyutludur.
7.)
Öğelerin bitişik bellek konumlarında depolandığı yerel bir programlama
bileşenidir.
Nesnelerin hiçbir zaman bitişik yerlerde saklanmadığı Java'nın koleksiyon
çerçevesinden bir sınıftır.
8.)
length değişkeni, Dizinin uzunluğunu belirlemek için kullanılır.
ArrayList öğesinin boyutunu belirlemek için size () yöntemi kullanılır.
9.)
Belirtilen öğeleri veya nesneleri depolamak için ArrayList'ten daha az
bellek alır.
Nesneleri depolamak için Diziden daha fazla bellek alır.
9.)
Dizi üzerinde yineleme yapmak, ArrayList üzerinden yinelemekten daha hızlıdır
ArrayList üzerinden yineleme, performans açısından önemli ölçüde yavaştır.
----------------------------------------------------------------------------
👉 ANR nedir?
Android mülakat soruları arasında en önemlisi de ANR’nin ne olduğu
üzerinedir. ANR (Application Not Responding), “Uygulama Yanıt Vermiyor”
anlamına gelen ve sistem tarafından gösterilen bir dialogdur.
Bir uygulama uzun bir süre boyunca yanıt vermediğinde kullanıcıya görünen
bir iletişim kutusudur.
----------------------------------------------------------------------------
👉 Content Provider nedir?
Content Provider, uygulamalarda kullanılan yerel verileri başka bir
uygulamanın kullanımına açılması durumunda veriler üzerinde değişiklik
yapma üzerine kullanılan bir yapıdır.
Content proviverlar, verinin saklanma ve iletilme yönteminden bağımsız olarak
veriyi güvenli bir şekilde diğer uygulamalara sunar. Content providerlar
vasıtasıyla uygulamalar veriye direkt erişim sağlayabilirler. Örneğin;
Calendar, SMS, Contact API’ları bu şekilde çalışmaktadır.
-----------------------------------------------------------------------------
Android Lifecycle
onCreate () : Activity oluşturulur.
onStart () : Bu geri çağırma yöntemi, activity kullanıcı tarafından görünür hale geldiğinde çağrılır.
onResume () : Activity ön plandadır ve kullanıcı onunla etkileşim kurabilir.
onPause () : Activity, başka bir etkinlik tarafından kısmen engellenmiştir. Ön plandaki diğer etkinlik yarı şeffaftır.
onStop () : Activity tamamen gizlidir ve kullanıcı tarafından görülmez.
onDestroy () : Activity yok edilir ve bellekten kaldırılır.
-----------------------------------------------------------------------------
👉 Android’in temel yapı taşları nelerdir?
Activity: Aktivity, Android’deki herhangi bir uygulamanın ekran temsilidir.
Her etkinliğin, kullanıcı arayüzünüzü yerleştirebileceğiniz bir düzen dosyası
vardır.
Content Provider: İçerik sağlayıcılar, uygulamalar arasında veri paylaşır.
Service: Kullanıcı ile etkileşime girmeden uzun süreli işlemleri
gerçekleştirmek için arka planda çalışan bir bileşendir ve uygulama yok
edildiğinde bile çalışır.
Broadcast: Diğer uygulamalardan veya sistemin kendisinden gelen yayın
mesajlarına yanıt verir. Bu mesajlar bazen olaylar veya niyetler olarak
adlandırılır.
-----------------------------------------------------------------------------
Android Mimarisi 4 temel bileşenden oluşur:
Linux Kernel
Libraries
Android Framework
Android Applications
-----------------------------------------------------------------------------
Android'te veri saklamak için kaç yol vardır ?
5 yol vardır. Shared preferences, Internal Storage, Local cache,
External Storage, SQLite Database, Content Provider, Network Connection.
-----------------------------------------------------------------------------
SharedPreferences'e data yazarken commit() ve apply() methodlarının
farkı nedir?
commit() syncronous gerçekleşirken apply() asyncronous gerçekleşir.
Yani commit() çağrıldığında o işlemi hemen gerçekleştirir. apply() methodu
da arka planda gerçekleşir.
-----------------------------------------------------------------------------
Fragmentlarda empty constructora ihtiyaç var mıdır? Neden?
Fragment oluştururken empty constructor'a ihtiyaç vardır. Bazı durumlarda
(Screen rotation vs.) android frameworku fragmenti destroy edip tekrar
yaratır. Bu durumda framework tarafında fragment'ın empty constructor'ı
çağrılır. Eğer parametreli bir constructor eklemediysek empty constructor
yaratmaya ihtiyaç yoktur çünkü bu durumda java compiler empty constructor'u
kendi ekler. Fakat parametreli bir constructor tanımlarsak eğer bunun
yanında empty constructor tanımlamak zorundayız.
Parametreli bir constructor tanımlayıp empty constructor tanımlamazsak
uygulamamız çalışmaz mı? Çalışır. Fakat rotation change vs. gibi android
frameworkünün fragmenti yok edip tekrar yarattığı durumda
android.support.v4.app.Fragment$InstantiationException hatası alırsınız.
-----------------------------------------------------------------------------
Kaç farklı veri taşıma yöntemi vardır? Bunlardan en performanslısı
hangisidir?
Interface ile veri taşıma
Bundle veya Intent ile veri taşıma
Parcelable ve serializable ile veri taşıma
Uzak sunucu ile veri taşıma
Shared Preferences ile veri taşıma
Static keyword veya singleton ile veri taşıma(Burada singleton’ın bir anti
patern olduğunu mutlaka belirtin)
on activity result ile activityler arası veri taşıma
En performanslı çalışan sorunun cevabı primitive tipler için Bundle veya
Intent, referans tipliler için ise Parcelable ile veri taşımadır.
-----------------------------------------------------------------------------
Serialization ve deserialization nedir?
Referans tipli bir classın nesnesinin bütün değişkenlerini ve constructor
ile beraber stringe çevirme işlemine serialization denir. Daha sonra
stringten classa çevirme işlemine de deserialization denir. Ek bilgi olarak
parcelable ile serialization aynı işi yapıyor fakat parcelable 10 kat daha
hızlıdır. Sebebi ise serialization bir java kütüphanesidir ve herhangi bir
web, masaüstü projesinde kullanılır. Parcelable ise bir Android
kütüphanesidir yani yalnızca Android projelerinde kullanılır. Son bir
toparlama olarak da şöyle bir bilgi vereyim, primitive tip taşımak
istiyorsak en hızlı veri taşıma yöntemi Intent veya Bundle , referans tipli
bir değişken taşımak istiyorsak Parcelable işimizi görecektir.
-----------------------------------------------------------------------------
Fragmentlar neden hep frame layouta ekleniyor?
Bilindiği üzere herhangi bir layouta da fragment eklenebilir ilk önce bu
bilgiyi bilmekte fayda var. Neden hep frame layout sorusuna gelirsek,
yapısı gereği layoutların içinde en az özellik sunan layout, frame
layouttır ki zaten biz farklı bir layout eklesek de onun özelliklerini
kullanmayacağız. Diğer layoutlara göre daha az işlemci gücü harcar ve bu da
fragmentların frame layouta eklenmesinin nedenidir.
-----------------------------------------------------------------------------
Singleton Pattern nedir?
İsminden de anlaşılacağı üzere singleton tasarım deseni, hazırlayacağımız
sınıftan sadece bir örneğinin oluşturulmasını sağlar. Bu sayede nesnenin
kopyalanmasını yada yeni bir tane oluşturmasını engeller ve nesneye ihtiyaç
duyulduğunda o nesnenin daha önceden oluşturulan örneği çağırır. Veritabanı
bağlantılarında, port bağlantılarında, yada dosya işlemleri gibi tek bir
nesneye ihtiyaç duyduğumuz zamanlarda kullanırız.
-----------------------------------------------------------------------------
Solid prensipleri nedir?
Bir metot veya bir class ne amaç ile yazılıyorsa içerikte o amaç ile ilgili
kodların olması gerektiği prensip.
-----------------------------------------------------------------------------
Abstrack class ile interface arasında fark nedir?
Interface’lerin bütün metotları implement etmek zorunludur
Abstrack classlarda sadece abstrack metotlar implement etmek zorunludur.
Interface’lerde can-do ilişkisi vardır.
Abstrack classlarda is-a ilişkisi vardır.
Bir sınıf sadece bir abstrack classı inherit edebilir.
Bir sınıf birden çok interface’i inherit edebilir
-----------------------------------------------------------------------------
Application nedir?
Application class’ı Android’in temeli olarak görülebilir. Android’in
gerçekleştirdiği diğer eylem ve hizmetlerin tüm bilgilerini barındıran ana
class’dır. Program çalıştırıldığında Android’de her şeyden önce ilk bu
class başlatılır.
-----------------------------------------------------------------------------
Android’in GUI’sının depolandığı yere ne ad verilir?
Android’in GUI’sı “Android SDK” adlı bir yerde depolanır. Ne olduğunu şöyle
bir örnekle açıklayalım. Bahçeye gitmeyi ve orada çalışmayı planladığınızı
hayal edin. Neye ihtiyaç duyarsınız? Araçlara aletlere. Araçlar nerede
saklanır? Çoğunlukla bir kulübede. Android SDK da bu kulübe gibidir.
Geliştiricinin kolay erişimi için tüm gerekli ve önemli araçları içerisinde
depolar.
-----------------------------------------------------------------------------
Implicit ve explicit intent’leri açıklayın.
Implicit intent (üstü kapalı) kullanıldığında Android arayüzü işleminizi
gerçekleştirmeye yardımcı olabilecek ayarlar için sistemi kontrol eder. Explicit intent (açık) ise işlem gerçekleştirilirken sisteminizin kullanması gereken bileşenleri belirtirsiniz. Basitleştirmek gerekirse sisteminize ne yapacağını söyler ve esnekliğe yer bırakmazsınız.
-----------------------------------------------------------------------------
Android hangi bytecode’u kullanır?
-dalvik.
Android sisteminde adapter’lar, AdapterView’ı
(kullanıldığı belli senaryolara göre ne olduğu değişir) harici bir veri
kaynağıyla bağlamak için kullanılır.
-----------------------------------------------------------------------------
Soru 10: “AsyncTask” ve “Thread” arasındaki fark nedir?
AsyncTask’ler kısa süreli işlemlerle (en fazla 5 saniye) çalışmak için
kullanılır. Thread’ler daha uzun işlemler içindir.
-----------------------------------------------------------------------------
Android Design Patterns:
1. Singleton--------------------------------
-kotlinde;
object Singleton {
fun doSomething(){
}
}
-javada;
public final class Singleton{
@NotNull
public static final Singleton INSTANCE; //singleton olacağı için static olur.
public final void doSomething() {
}
private Singleton() {
}
static {
Singleton var0 = new Singleton(); //singleton olduğu için hep 1 tane
INSTANCE = var0; //instance oluşturacak.
}
}
2. Factory Pattern ---------------------------------
benzer(aynı) type'lardaki nesnelerin hangisinin create edileceğini ayırt
etmeye çalışır.
yani farklı nesneler oluşturduk ama tipleri aynı, hangisin seçileceğine karar
veriliyor.
3. Builder Pattern ---------------------------------
4. Facade Pattern ---------------------------------
Dependency Injection Pattern? ---------------------------------
5. Adapter Pattern ---------------------------------
6. Abstract Factory Pattern---------------------------------
-----------------------------------------------------------------------------
anti patterns
------------------------------------MVVM------------------------------------
Model - View - ViewModel.
Data Source - UI - Business Logic.
Repository,ViewModel ve View'dan oluşur.ViewModel,Repo'ya request data(istek)
atar. Repo'dan dönen datalar(return data) ViewModela ulaşır. Business
logic işlemleri ViewModel'da gerçekleşir. en son sonuçlar ViewModel'dan
View'a aktarılır ve View'da sadece görünümleri bağlama logic'i olur,
business logic değil.
Not: ViewModel kiminle iletişim halinde olduğundan haberdar olmamalıdır.
--------------------------------------------------------------
HashSet, yinelenen değerlere izin vermez. HashMap, anahtar,
değer çiftlerini saklar ve yinelenen anahtarlara izin vermez.
Anahtar yineleniyorsa, eski anahtar yeni değerle değiştirilir.