- https://developer.android.com/kotlin/style-guide
- https://kotlinlang.org/docs/coding-conventions.html
- https://developer.android.com/develop/ui/compose/performance/bestpractices
- https://developer.android.com/develop/ui/compose/state-hoisting#best-practice
- https://developer.android.com/guide/components/activities/parcelables-and-bundles
-
This page provides recommendations and best practices for using Parcelable and Bundle objects.
-
- https://developer.android.com/kotlin/coroutines/coroutines-best-practices
- https://developer.android.com/topic/architecture/recommendations
- https://developer.android.com/topic/libraries/architecture/viewmodel#best-practices
- https://developer.android.com/training/data-storage/use-cases
# shows as a tree
./gradlew dependencies
# shows as a list
./gradlew androidDependencies
# shows as a tree
./gradlew app:dependencies --configuration <buildVariant>CompileClasspath
./gradlew app:dependencies --configuration debugCompileClasspath
# shows as a list
./gradlew app:androidDependencies
./gradlew app:dependencies --configuration <buildVariant>CompileClasspath | grep "^+---" | sort
./gradlew app:dependencies --configuration debugCompileClasspath | grep "^+---" | sort
# for more details
./gradlew help --task app:dependencies
./gradlew help --task app:androidDependencies
./gradlew app:dependencies --configuration implementation | grep '+--- project' | sort
./gradlew app:dependencyInsight --configuration <buildVariant>CompileClasspath --dependency <group>:<name>
./gradlew app:dependencyInsight --configuration debugCompileClasspath --dependency org.jetbrains.kotlin:kotlin-stdlib
# for more details
./gradlew help --task app:dependencyInsight
# Build the app module with the product flavor "foo" and the build type "debug"
./gradlew app:assembleFooDebug
# Build all the modules with all the build variants
./gradlew assemble
https://developer.android.com/build/building-cmdline#DebugMode
# Install the app module with the product flavor "foo" and the build type "debug"
./gradlew app:installFooDebug
# Install with all the build variants
./gradlew install
./gradlew test
./gradlew connectedAndroidTest
# Alternatively
# https://docs.gradle.org/current/userguide/command_line_interface.html#sec:name_abbreviation
./gradlew cAT
./gradlew <module>:test<buildVariant>UnitTest
./gradlew <module>:connected<buildVariant>AndroidTest
The following custom task in the project-level build.gradle
is to delete the project-level build
directory when clicking the menu bar > Build
> Clean Project
.
task clean(type: Delete) {
delete rootProject.buildDir
}
https://developer.android.com/reference/kotlin/android/R.color
https://developer.android.com/reference/kotlin/android/R.string
val encoded: String = "<>&'\"".htmlEncode() // <>&'"
val decoded: String = String =
Html.fromHtml("<>&'"", Html.FROM_HTML_MODE_COMPACT).toString() // <>&'"
String.htmlEncode is a part of the Core KTX library and is syntactic sugar for TextUtils.htmlEncode .
val color: Color = Color.valueOf(0x11223344)
You can debug a release build only if you set both minifyenabled false
and debuggable false
.
// app/build.gradle
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable true
signingConfig signingConfigs.debug
}
}
}
// app/build.gradle.kts
android {
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
isDebuggable = true
signingConfig = signingConfigs.getByName("debug")
}
}
}
Add the following to proguard-rule.pro
.
-keepattributes SourceFile,LineNumberTable
/** isOpen and close() require "androidx.drawerlayout:drawerlayout:1.1.0" or higher. */
override fun onBackPressed() {
if (drawerLayout.isOpen) {
drawerLayout.close()
return
}
super.onBackPressed()
}
OnBackPressedDispatcher.hasEnabledCallbacks()
returns true if both of the following are met.- There is at least one callback registered with this dispatcher.
- Your Activity is being between
onStart()
andonStop()
(both inclusive). If you overrideonStart()
and/oronStop()
, it is betweensuper.onStart()
andsuper.onStop()
. - Even if you pass a Fragment to
OnBackPressedDispatcher.addCallback(...)
, the Fragment's lifecycle does not affectOnBackPressedDispatcher.hasEnabledCallbacks()
.
- If your Activitiy overrides
onBackPressed()
but you forget to callsuper.onBackPressed()
in it, your callback will never be called.
class MyCustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : View(context, attrs, defStyle) {
init {
context.withStyledAttributes(
attrs,
R.styleable.MyCustomView,
defStyle,
0
) { // simpler than Theme.obtainStyledAttributes(...)
// ...
}
}
}
val cookieManager = CookieManager.getInstance()
val url1 = "example.com"
val url2 = "example.com/foo"
val url3 = "sub.example.com"
val url4 = "https://example.com"
val url5 = "http://example.com"
cookieManager.setCookie(url1, "a=1")
cookieManager.setCookie(url2, "b=2")
cookieManager.setCookie(url3, "c=3")
cookieManager.setCookie(url4, "d=4")
cookieManager.setCookie(url5, "e=5")
cookieManager.setCookie(url5, "e=5!")
val cookie1: String = cookieManager.getCookie(url1) // a = 1; b = 2; d = 4; e = 5!
val cookie2: String = cookieManager.getCookie(url2) // a = 1; b = 2; d = 4; e = 5!
val cookie3: String = cookieManager.getCookie(url3) // c = 3
val cookie4: String = cookieManager.getCookie(url4) // a = 1; b = 2; d = 4; e = 5!
val cookie5: String = cookieManager.getCookie(url5) // a = 1; b = 2; d = 4; e = 5!
A | B | Note |
---|---|---|
Activity.resources Fragment.resources View.resources |
||
Activity.context.resources Fragment.requireContext().resources View.context.resources |
||
Activity.getString(...) Fragment.getString(...) |
||
Activity.resources.getString(...) Fragment.requireContext().getString(...) Fragment.resources.getString(...) |
||
String.toUri() |
Uri.parse(...) |
|
bundleOf(...) |
Bundle().apply { ... } |
|
CharSequence.isDigitsOnly() |
(old-school ways to check if a string contains only digits) | |
Context.withStyledAttributes(...) |
obtainStyledAttributes(...) |
|
Intent.getStringExtra("foo") |
Intent.extras?.getString("foo") |
The same goes for other types. |
view in fun onViewCreated(view: View) |
requireView() in fun onViewCreated(view: View) |
|
Uri.encode(url) |
URLEncoder.encode(url, Charsets.UTF_8.name()) |