برای اپلیکیشن هایی که بیش از 64K متد دارن (K یعنی 1024) به عبارتی دیگر، اپ هایی که بیش از 65,536 متد دارن، باید multidex فعال بشه در غیر این صورت ارور میده.
نحوه فعال سازی در sdkهای پایین تر از 20:
برای اپلیکیشن هایی که بیش از 64K متد دارن (K یعنی 1024) به عبارتی دیگر، اپ هایی که بیش از 65,536 متد دارن، باید multidex فعال بشه در غیر این صورت ارور میده.
نحوه فعال سازی در sdkهای پایین تر از 20:
گریدل productFlavor هایی که dimension مشابه دارن رو باهم ادغام نمیکنه. مثال زیر به خوبی این قضیه رو نشون میده:
flavorDimensions "dev", "test"
productFlavors{
free {
dimension "dev"
applicationIdSuffix ".free"
buildConfigField "String", "BASE_URL", "\"https://freeversion.com\""
}
paid {
dimension "dev"
applicationIdSuffix ".paid"
buildConfigField "String", "BASE_URL", '"https://paidversion.com"'
}
qa{
dimension "test"
}
}
اگر بخواهیم از یک سورس کد دو تا خروجی با ویژگی های متفاوت بگیریم (مثلا نسخه free و paid) از productFlavor استفاده میکنیم. توی هر نسخه میشه ریسورس های مختلفی داد که در ادامه توضیح میدم.
برای این کار api key رو توی فایل gradle.properties تعریف کرده و در لیست gitignore اون رو به صورت زیر اضافه میکنیم:
/gradle.properties
به صورت پیش فرض دو نسخه از اپلیکیشن میتونه بیلد بشه، نسخه دیباگ و نسخه release. میتونیم نسخه های دیگه با ویژگی های کاستوم هم اضافه کنیم که این کار در بلوک buildTypes انجام میشه. حالا به چه دردی میخوره؟
میشه به هر variant یک سری buildConfigField اضافه کرد و مثلا URL یا apiKey رو توی نسخه های مختلف مدیریت کرد. مثلا:
توی کاتلین مفهوم استاتیک مثل جاوا وجود نداره. با این حال یه سری امکاناتی برای معرفی فیلد و متدهای استاتیک در نظر گرفته شده است.
در هر کلاسی میشه companion object تعریف کرد و داخل بلاک آن فیلدها و متدهای استاتیک تعریف کرد.
در کاتلین برای مقداردهی فیلدهایی که در ابتدای کلاس معرفی شده و قرار است در اواسط کلاس مقداردهی شوند، دو روش وجود دارد:
1. {...} by lazy
2. lateinit
{...} by lazy همون جا مقدار متغیر مشخص میشه اما به محض استفاده از آن متغیر مقداردهی می شود. حتما باید از نوع val باشه.
lateinit نمیتونه nullable باشه و حتما باید از نوع var باشد.
اگر کلاس viewModel دارای آرگومان باشد، در این صورت برای instance کردن آن باید کلاس فکتوری تعریف کنیم:
class ViewModelFactory(private val num:Int): ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass.isAssignableFrom(MyViewModel::class.java)){
return MyViewModel(num) as T
}
throw IllegalArgumentException("Not Found")
}
}
این کلاس همیشه به همین فرمت نوشته میشه.