Android Studio Cheatsheet
Android Studio - Die offizielle IDE für Android Development
Android Studio ist das offizielle Integrated Development Environment (IDE) für das Android-Betriebssystem von Google, das auf der IntelliJ IDEA-Software von JetBrains basiert und speziell für Android-Entwicklung entwickelt wurde. < p>
Inhaltsverzeichnis
- [Installation](LINK_0 -%20(LINK_0)
- [Projektstruktur](LINK_0__ -%20[Benutzeroberfläche](LINK_0 -%20Aktivitäten%20und%20Fragmente
- Ausstellungen und Ansichten
- Ressourcen
- [Datenspeicher](LINK_0 -%20[Networking](LINK_0 -%20Test
- [Debugging](_LINK_0__ -%20[Performance](LINK_0 -%20(__LINK_0___)
- (__LINK_0___)
- Keyboard Shortcuts
- Beste Praktiken
- (__LINK_0___)
Installation
Systemanforderungen
# Windows
# 64-bit Microsoft Windows 8/10/11
# x86_64 CPU architecture; 2nd generation Intel Core or newer, or AMD CPU with support for Windows Hypervisor
# 8 GB RAM or more
# 8 GB of available disk space minimum (IDE + Android SDK + Android Emulator)
# 1280 x 800 minimum screen resolution
# macOS
# macOS 10.14 (Mojave) or higher
# ARM-based chips, or 2nd generation Intel Core or newer with support for Hypervisor.Framework
# 8 GB RAM or more
# 8 GB of available disk space minimum (IDE + Android SDK + Android Emulator)
# 1280 x 800 minimum screen resolution
# Linux
# Any 64-bit Linux distribution that supports Gnome, KDE, or Unity DE; GNU C Library (glibc) 2.31 or later
# x86_64 CPU architecture; 2nd generation Intel Core or newer, or AMD processor with support for AMD Virtualization (AMD-V) and SSSE3
# 8 GB RAM or more
# 8 GB of available disk space minimum (IDE + Android SDK + Android Emulator)
# 1280 x 800 minimum screen resolution
```_
### Download und Installieren
```bash
# Download from https://developer.android.com/studio
# Run the installer and follow the setup wizard
# Verify installation
android --version
adb --version
```_
### SDK Setup
```bash
# Open Android Studio
# Go to Tools > SDK Manager
# Install required SDK platforms and tools
# Command line SDK manager
sdkmanager --list
sdkmanager "platforms;android-33"
sdkmanager "build-tools;33.0.0"
sdkmanager "system-images;android-33;google_apis;x86_64"
```_
## Erste Schritte
### Neues Projekt erstellen
```bash
# File > New > New Project
# Choose a template (Empty Activity, Basic Activity, etc.)
# Configure project settings:
# - Name: MyApp
# - Package name: com.example.myapp
# - Save location: /path/to/project
# - Language: Java/Kotlin
# - Minimum SDK: API 21 (Android 5.0)
```_
### Projektvorlagen
```kotlin
// Empty Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
// Basic Activity with Fragment
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
}
}
// Bottom Navigation Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
navView.setupWithNavController(navController)
}
}
```_
## Projektstruktur
MyApp/ ├── app/ │ ├── src/ │ │ ├── main/ │ │ │ ├── java/com/example/myapp/ │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── fragments/ │ │ │ │ ├── adapters/ │ │ │ │ ├── models/ │ │ │ │ └── utils/ │ │ │ ├── res/ │ │ │ │ ├── layout/ │ │ │ │ ├── values/ │ │ │ │ ├── drawable/ │ │ │ │ ├── mipmap/ │ │ │ │ └── menu/ │ │ │ └── AndroidManifest.xml │ │ ├── test/ │ │ └── androidTest/ │ ├── build.gradle │ └── proguard-rules.pro ├── gradle/ ├── build.gradle ├── settings.gradle └── gradle.properties ```_
Benutzeroberfläche
Aktivitäten
```kotlin // Basic Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
// Initialize views
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
// Handle click
Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show()
}
}
override fun onStart() {
super.onStart()
// Activity is becoming visible
}
override fun onResume() {
super.onResume()
// Activity is now visible and interactive
}
override fun onPause() {
super.onPause()
// Activity is partially obscured
}
override fun onStop() {
super.onStop()
// Activity is no longer visible
}
override fun onDestroy() {
super.onDestroy()
// Activity is being destroyed
}
}
// Activity with Intent class SecondActivity : AppCompatActivity() { companion object { const val EXTRA_MESSAGE = "extra_message"
fun newIntent(context: Context, message: String): Intent {
return Intent(context, SecondActivity::class.java).apply {
putExtra(EXTRA_MESSAGE, message)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val message = intent.getStringExtra(EXTRA_MESSAGE)
findViewById<TextView>(R.id.textView).text = message
}
}
// Starting an Activity val intent = SecondActivity.newIntent(this, "Hello from MainActivity!") startActivity(intent)
// Starting Activity for Result private val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val data = result.data?.getStringExtra("result_data") // Handle result } }
launcher.launch(intent) ```_
Duftstoffe
```kotlin // Basic Fragment class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button = view.findViewById<Button>(R.id.button)
button.setOnClickListener {
// Handle click
}
}
}
// Fragment with Arguments class DetailFragment : Fragment() {
companion object {
private const val ARG_ITEM_ID = "item_id"
fun newInstance(itemId: String) = DetailFragment().apply {
arguments = Bundle().apply {
putString(ARG_ITEM_ID, itemId)
}
}
}
private val itemId: String by lazy {
arguments?.getString(ARG_ITEM_ID) ?: ""
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_detail, container, false)
}
}
// Fragment Transaction supportFragmentManager.beginTransaction() .replace(R.id.container, DetailFragment.newInstance("123")) .addToBackStack(null) .commit() ```_
Layouts und Ansichten
Lineares Layout
```xml
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="18sp" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click Me" />
```_
Layout einschränken
```xml
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
```_
Recycling Blick
```kotlin
// Adapter
class MyAdapter(private val items: List
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.textView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_layout, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = items[position]
}
override fun getItemCount() = items.size
}
// Setup RecyclerView
val recyclerView = findViewById
ViewPager2 mit Fragmenten
```kotlin // Fragment Adapter class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> FirstFragment()
1 -> SecondFragment()
2 -> ThirdFragment()
else -> FirstFragment()
}
}
}
// Setup ViewPager2
val viewPager = findViewById
// With TabLayout
val tabLayout = findViewById
Ressourcen
Streicher
```xml
<plurals name="numberOfItems">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
val appName = getString(R.string.app_name) val welcomeMessage = getString(R.string.welcome_message, "John") val itemCount = resources.getQuantityString(R.plurals.numberOfItems, count, count) ```_
Farben
```xml
val color = ContextCompat.getColor(this, R.color.purple_500) textView.setTextColor(color) ```_
Abmessungen
```xml
Stile und Themen
```xml
<style name="CustomButton" parent="Widget.MaterialComponents.Button">
<item name="android:textColor">@color/white</item>
<item name="backgroundTint">@color/purple_500</item>
<item name="cornerRadius">8dp</item>
</style>
```_
Datenspeicherung
GemeinsamePräferenzen
```kotlin // Save data val sharedPref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE) with(sharedPref.edit()) { putString("username", "john_doe") putInt("user_id", 123) putBoolean("is_logged_in", true) apply() }
// Read data val username = sharedPref.getString("username", "") val userId = sharedPref.getInt("user_id", 0) val isLoggedIn = sharedPref.getBoolean("is_logged_in", false) ```_
Zimmerdatenbank
```kotlin // Entity @Entity(tableName = "users") data class User( @PrimaryKey val id: Int, val name: String, val email: String )
// DAO
@Dao
interface UserDao {
@Query("SELECT * FROM users")
fun getAllUsers(): LiveData>
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
@Insert
suspend fun insertUser(user: User)
@Update
suspend fun updateUser(user: User)
@Delete
suspend fun deleteUser(user: User)
}
// Database @Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database"
).build()
INSTANCE = instance
instance
}
}
}
}
// Usage
class UserRepository(private val userDao: UserDao) {
val allUsers: LiveData> = userDao.getAllUsers()
suspend fun insert(user: User) {
userDao.insertUser(user)
}
} ```_
Dateispeicher
```kotlin // Internal storage val filename = "myfile.txt" val fileContents = "Hello, Android!" openFileOutput(filename, Context.MODE_PRIVATE).use { it.write(fileContents.toByteArray()) }
// Read from internal storage val content = openFileInput(filename).bufferedReader().useLines { lines -> lines.fold("") { some, text -> "$some\n$text" } }
// External storage if (isExternalStorageWritable()) { val file = File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "myfile.txt") file.writeText("Hello, External Storage!") }
private fun isExternalStorageWritable(): Boolean { return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED } ```_
Vernetzung
Zurück zur Übersicht
```kotlin // Add dependencies to build.gradle implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// Data model data class Post( val id: Int, val title: String, val body: String, val userId: Int )
// API interface
interface ApiService {
@GET("posts")
suspend fun getPosts(): List
@GET("posts/{id}")
suspend fun getPost(@Path("id") id: Int): Post
@POST("posts")
suspend fun createPost(@Body post: Post): Post
@PUT("posts/{id}")
suspend fun updatePost(@Path("id") id: Int, @Body post: Post): Post
@DELETE("posts/{id}")
suspend fun deletePost(@Path("id") id: Int): Response<Unit>
}
// Retrofit instance object RetrofitInstance { private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
val api: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
// Usage in ViewModel
class PostViewModel : ViewModel() {
private val _posts = MutableLiveData>()
val posts: LiveData
> = _posts
fun fetchPosts() {
viewModelScope.launch {
try {
val response = RetrofitInstance.api.getPosts()
_posts.value = response
} catch (e: Exception) {
// Handle error
}
}
}
} ```_
OkHtp
```kotlin // Add dependency implementation 'com.squareup.okhttp3:okhttp:4.10.0'
// Basic usage val client = OkHttpClient()
val request = Request.Builder() .url("https://api.example.com/data") .build()
client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // Handle failure }
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
val responseBody = response.body?.string()
// Handle response
}
}
})
// With interceptors val client = OkHttpClient.Builder() .addInterceptor { chain -> val request = chain.request().newBuilder() .addHeader("Authorization", "Bearer $token") .build() chain.proceed(request) } .build() ```_
Prüfung
Einheitsprüfung
```kotlin // Add dependencies testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:4.6.1'
// Test class class CalculatorTest {
private lateinit var calculator: Calculator
@Before
fun setUp() {
calculator = Calculator()
}
@Test
fun addition_isCorrect() {
val result = calculator.add(2, 2)
assertEquals(4, result)
}
@Test
fun division_byZero_throwsException() {
assertThrows(ArithmeticException::class.java) {
calculator.divide(10, 0)
}
}
}
// Testing with Mockito class UserRepositoryTest {
@Mock
private lateinit var apiService: ApiService
@Mock
private lateinit var userDao: UserDao
private lateinit var repository: UserRepository
@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
repository = UserRepository(apiService, userDao)
}
@Test
fun getUser_returnsUser() = runTest {
val user = User(1, "John", "john@example.com")
`when`(apiService.getUser(1)).thenReturn(user)
val result = repository.getUser(1)
assertEquals(user, result)
verify(apiService).getUser(1)
}
} ```_
Instrumentierte Prüfung
```kotlin // Add dependencies androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// Test class @RunWith(AndroidJUnit4::class) class MainActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)
@Test
fun button_click_showsToast() {
onView(withId(R.id.button))
.perform(click())
onView(withText("Button clicked!"))
.inRoot(withDecorView(not(activityRule.scenario.onActivity { it.window.decorView })))
.check(matches(isDisplayed()))
}
@Test
fun recyclerView_displaysItems() {
onView(withId(R.id.recyclerView))
.check(matches(isDisplayed()))
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(2))
onView(withText("Item 3"))
.check(matches(isDisplayed()))
}
} ```_
Debugging
Protokoll
```kotlin // Log levels Log.v(TAG, "Verbose message") Log.d(TAG, "Debug message") Log.i(TAG, "Info message") Log.w(TAG, "Warning message") Log.e(TAG, "Error message")
// With exception try { // Some code } catch (e: Exception) { Log.e(TAG, "Error occurred", e) }
// Timber (recommended logging library) implementation 'com.jakewharton.timber:timber:5.0.1'
// Initialize in Application class class MyApplication : Application() { override fun onCreate() { super.onCreate() if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) } } }
// Usage Timber.d("Debug message") Timber.e(exception, "Error occurred") ```_
Debugging Tools
```kotlin // Breakpoints // Set breakpoints by clicking on the line number gutter // Conditional breakpoints: right-click on breakpoint
// Debug console // Use "Evaluate Expression" (Alt+F8) to execute code during debugging
// Layout Inspector // Tools > Layout Inspector // Inspect view hierarchy and properties
// Database Inspector // View > Tool Windows > Database Inspector // Inspect Room database contents
// Network Inspector // View > Tool Windows > Network Inspector // Monitor network requests and responses ```_
Leistung
Profilierung des Speichers
```kotlin // Memory Profiler // View > Tool Windows > Profiler // Select your app and start a memory profiling session
// Detecting memory leaks class MainActivity : AppCompatActivity() { private var leakyHandler: Handler? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Bad: This creates a memory leak
leakyHandler = Handler(Looper.getMainLooper())
leakyHandler?.postDelayed({
// This runnable holds a reference to the activity
}, 60000)
}
override fun onDestroy() {
super.onDestroy()
// Good: Clean up to prevent memory leaks
leakyHandler?.removeCallbacksAndMessages(null)
leakyHandler = null
}
}
// Using WeakReference class MyHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { private val activityRef = WeakReference(activity)
override fun handleMessage(msg: Message) {
val activity = activityRef.get()
if (activity != null && !activity.isFinishing) {
// Handle message
}
}
} ```_
CPU Profilierung
```kotlin // CPU Profiler // View > Tool Windows > Profiler // Select your app and start a CPU profiling session
// Optimizing RecyclerView
class OptimizedAdapter : RecyclerView.Adapter
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// Reuse view holders
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_layout, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// Minimize work in onBindViewHolder
holder.bind(items[position])
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textView: TextView = itemView.findViewById(R.id.textView)
fun bind(item: String) {
textView.text = item
}
}
}
// Using DiffUtil for efficient updates
class MyDiffCallback(
private val oldList: List
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
// Update adapter with DiffUtil
fun updateItems(newItems: List
Bausystem
Gradle Konfiguration
```groovy // app/build.gradle android { compileSdk 33
defaultConfig {
applicationId "com.example.myapp"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
}
productFlavors {
free {
dimension "version"
applicationIdSuffix ".free"
}
paid {
dimension "version"
applicationIdSuffix ".paid"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
dataBinding true
}
}
dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
} ```_
Variablen erstellen
```bash
Build debug APK
./gradlew assembleDebug
Build release APK
./gradlew assembleRelease
Build specific flavor
./gradlew assembleFreeDebug ./gradlew assemblePaidRelease
Install on device
./gradlew installDebug
Run tests
./gradlew test ./gradlew connectedAndroidTest
Clean build
./gradlew clean ```_
Veröffentlichungen
Konfiguration unterzeichnen
```groovy // app/build.gradle android { signingConfigs { release { storeFile file('path/to/keystore.jks') storePassword 'store_password' keyAlias 'key_alias' keyPassword 'key_password' } }
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
} ```_
Kennzeichnete APK generieren
```bash
Using Android Studio
Build > Generate Signed Bundle / APK
Choose APK or Android App Bundle
Select keystore and enter passwords
Choose build variant
Click Finish
Using command line
./gradlew assembleRelease
Generate App Bundle (recommended for Play Store)
./gradlew bundleRelease ```_
ProGuard/R8 Konfiguration
```proguard
proguard-rules.pro
Keep model classes
-keep class com.example.myapp.model.* { ; }
Keep Retrofit interfaces
-keep interface com.example.myapp.api.* { ; }
Keep Gson annotations
-keepattributes Signature -keepattributes Annotation -keep class com.google.gson.* { ; }
Keep Parcelable classes
-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; }
Remove logging in release builds
-assumenosideeffects class android.util.Log { public static *** d(...); public static *** v(...); public static *** i(...); } ```_
Keyboard Shortcuts
Navigation
```bash
General
Ctrl+Shift+A # Find Action Ctrl+Shift+N # Find File Ctrl+Alt+Shift+N # Find Symbol Ctrl+E # Recent Files Ctrl+Shift+E # Recent Locations
Code Navigation
Ctrl+B # Go to Declaration Ctrl+Alt+B # Go to Implementation Ctrl+U # Go to Super Method Ctrl+H # Type Hierarchy Ctrl+Alt+H # Call Hierarchy
Search and Replace
Ctrl+F # Find Ctrl+R # Replace Ctrl+Shift+F # Find in Path Ctrl+Shift+R # Replace in Path ```_
Bearbeitung
```bash
Code Generation
Alt+Insert # Generate Code Ctrl+O # Override Methods Ctrl+I # Implement Methods Ctrl+Alt+T # Surround With
Refactoring
Shift+F6 # Rename Ctrl+Alt+M # Extract Method Ctrl+Alt+V # Extract Variable Ctrl+Alt+F # Extract Field Ctrl+Alt+C # Extract Constant
Code Formatting
Ctrl+Alt+L # Reformat Code Ctrl+Alt+O # Optimize Imports Ctrl+Shift+Up/Down # Move Line Up/Down ```_
Debugging
```bash
Debug Actions
F8 # Step Over F7 # Step Into Shift+F8 # Step Out F9 # Resume Program Ctrl+F8 # Toggle Breakpoint Ctrl+Shift+F8 # View Breakpoints
Run Actions
Shift+F10 # Run Shift+F9 # Debug Ctrl+F2 # Stop ```_
Best Practices
Architektur
```kotlin
// MVVM Architecture
class UserViewModel(private val repository: UserRepository) : ViewModel() {
private val _users = MutableLiveData>()
val users: LiveData
> = _users
private val _loading = MutableLiveData<Boolean>()
val loading: LiveData<Boolean> = _loading
fun loadUsers() {
viewModelScope.launch {
_loading.value = true
try {
val userList = repository.getUsers()
_users.value = userList
} catch (e: Exception) {
// Handle error
} finally {
_loading.value = false
}
}
}
}
// Repository Pattern
class UserRepository(
private val apiService: ApiService,
private val userDao: UserDao
) {
suspend fun getUsers(): List
// Dependency Injection with Hilt @HiltAndroidApp class MyApplication : Application()
@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var userRepository: UserRepository }
@Module @InstallIn(SingletonComponent::class) object NetworkModule { @Provides @Singleton fun provideApiService(): ApiService { return Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService::class.java) } } ```_
Leistung
```kotlin // Use ViewBinding instead of findViewById class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {
// Handle click
}
}
}
// Lazy initialization
class MyActivity : AppCompatActivity() {
private val adapter by lazy { MyAdapter() }
private val viewModel by viewModels
// Use coroutines for background work class DataRepository { suspend fun fetchData(): List = withContext(Dispatchers.IO) { // Network call or database operation apiService.getData() } } ```_
Sicherheit
```kotlin // Network Security Config // res/xml/network_security_config.xml
// AndroidManifest.xml
// Certificate Pinning val certificatePinner = CertificatePinner.Builder() .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") .build()
val client = OkHttpClient.Builder() .certificatePinner(certificatePinner) .build()
// Secure SharedPreferences val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build()
val sharedPreferences = EncryptedSharedPreferences.create( context, "secret_shared_prefs", masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) ```_
Fehlerbehebung
Gemeinsame Themen
```bash
Gradle sync issues
File > Invalidate Caches and Restart
Delete .gradle folder and rebuild
Build errors
./gradlew clean ./gradlew build --stacktrace
Emulator issues
AVD Manager > Wipe Data
Cold Boot Now
Memory issues
Increase heap size in gradle.properties
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m
Dependency conflicts
./gradlew app:dependencies
Check for version conflicts and exclude transitive dependencies
```_
Debugging Tipps
```kotlin // Use meaningful log tags companion object { private const val TAG = "MainActivity" }
// Log method entry and exit override fun onCreate(savedInstanceState: Bundle?) { Log.d(TAG, "onCreate() called") super.onCreate(savedInstanceState) // ... Log.d(TAG, "onCreate() finished") }
// Use assertions for debugging assert(user != null) { "User should not be null at this point" }
// Use TODO() for unimplemented code fun notImplementedYet() { TODO("This function is not implemented yet") } ```_
--
Zusammenfassung
Android Studio ist eine leistungsstarke IDE, die umfassende Tools für Android-Entwicklung bietet. Zu den wichtigsten Merkmalen gehören:
- *Intelligent Code Editor: Erweiterte Code-Vervollständigung, Refactoring und Analyse
- *Visual Layout Editor: Drag-and-Drop-Interface-Design mit Strenge-Layout
- APK Analyzer: Größe und Zusammensetzung der APK analysieren
- Fast Emulator: Schneller und funktionsreicher Android-Emulator
- Instant Run: Änderungen sofort anzeigen, ohne die gesamte App neu aufzubauen
- *Profiling Tools: Speicher, CPU und Netzwerkprofile zur Leistungsoptimierung
- ** Testing Support**: Gerätetests, Gerätetests und UI-Testrahmen
- Version Control: Eingebaut Git Unterstützung und Integration mit beliebten VCS
- *Gradle Build System: Flexible und leistungsstarke Bauautomatisierung
- *Plugin Ecosystem: Umfangreiche Plugin-Unterstützung für verbesserte Funktionalität
Android Studio optimiert den gesamten Android-Entwicklungs-Workflow von der Projekt-Erstellung bis zur Bereitstellung, so dass es das wesentliche Werkzeug für Android-Entwickler.
<= <= <= <================================================================================= Funktion copyToClipboard() {\cHFFFF} const commands = document.querySelectorAll('code'); alle Befehle = ''; Befehle. Für jede(cmd) => alle Befehle += cmd.textContent + '\n'); navigator.clipboard.writeText (allCommands); Alarm ('Alle Befehle, die in die Zwischenablage kopiert werden!'); }
Funktion generierenPDF() { Fenster.print(); }