引言

Android作为全球最流行的移动操作系统,拥有超过25亿活跃设备。掌握Android开发技能对于程序员来说至关重要。本指南将通过实战案例,从基础到高级,系统性地讲解Android开发的核心知识和技巧。

第一部分:Android开发环境搭建

1.1 开发工具选择

Android开发主要使用Android Studio,这是Google官方推荐的集成开发环境(IDE)。它基于IntelliJ IDEA,提供了代码编辑、调试、性能分析等完整功能。

安装步骤:

  1. 访问Android开发者官网
  2. 下载对应操作系统的安装包
  3. 运行安装程序,按照向导完成安装
  4. 首次启动时,会引导下载Android SDK和相关组件

1.2 创建第一个项目

在Android Studio中创建新项目:

// 选择Empty Activity模板
// 项目结构:
// - app/
//   - src/
//     - main/
//       - java/ (或 kotlin/)
//         - com.example.myapp/
//           - MainActivity.kt
//       - res/
//         - layout/
//           - activity_main.xml
//         - values/
//           - strings.xml
//         - drawable/
//       - AndroidManifest.xml
//   - build.gradle
// - build.gradle (项目级)

关键文件说明:

  • AndroidManifest.xml:应用的配置文件,声明Activity、权限等
  • MainActivity.kt:主Activity,应用入口
  • activity_main.xml:界面布局文件
  • build.gradle:项目构建配置

第二部分:Android基础组件

2.1 Activity生命周期

Activity是Android应用的基本组件,负责管理用户界面和交互。理解生命周期是开发的关键。

class MainActivity : AppCompatActivity() {
    private val TAG = "MainActivity"
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "onCreate: Activity被创建")
    }
    
    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart: Activity开始可见")
    }
    
    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume: Activity获得焦点")
    }
    
    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause: Activity失去焦点")
    }
    
    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop: Activity不可见")
    }
    
    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy: Activity被销毁")
    }
}

生命周期图解:

onCreate() → onStart() → onResume() → [运行状态] → onPause() → onStop() → onDestroy()

2.2 Fragment使用

Fragment是可重用的UI模块,可以在Activity中动态添加和移除。

// 创建Fragment
class MyFragment : Fragment() {
    private lateinit var textView: TextView
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 加载布局
        val view = inflater.inflate(R.layout.fragment_my, container, false)
        textView = view.findViewById(R.id.textView)
        return view
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 设置数据
        textView.text = "Hello from Fragment!"
    }
}

// 在Activity中使用Fragment
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 动态添加Fragment
        val fragment = MyFragment()
        supportFragmentManager.beginTransaction()
            .add(R.id.fragment_container, fragment)
            .commit()
    }
}

2.3 Intent和数据传递

Intent是Android组件间通信的桥梁,可以启动Activity、Service等。

// 显式Intent启动Activity
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("username", "张三")
intent.putExtra("age", 25)
startActivity(intent)

// 隐式Intent
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
startActivity(intent)

// 接收数据
class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        
        val username = intent.getStringExtra("username")
        val age = intent.getIntExtra("age", 0)
        
        val textView = findViewById<TextView>(R.id.textView)
        textView.text = "欢迎 $username,你今年 $age 岁"
    }
}

第三部分:UI开发与布局

3.1 常用布局

Android提供多种布局管理器,用于组织UI元素。

LinearLayout(线性布局):

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="标题"
        android:textSize="20sp"
        android:gravity="center"/>
    
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击我"/>
</LinearLayout>

ConstraintLayout(约束布局):

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OK"
        app:layout_constraintTop_toBottomOf="@id/textView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

3.2 RecyclerView使用

RecyclerView是现代Android开发中用于显示列表数据的首选组件。

// 1. 创建数据模型
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// 2. 创建Adapter
class UserAdapter(private val userList: List<User>) : 
    RecyclerView.Adapter<UserAdapter.UserViewHolder>() {
    
    class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val nameTextView: TextView = itemView.findViewById(R.id.nameTextView)
        val emailTextView: TextView = itemView.findViewById(R.id.emailTextView)
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_user, parent, false)
        return UserViewHolder(view)
    }
    
    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = userList[position]
        holder.nameTextView.text = user.name
        holder.emailTextView.text = user.email
    }
    
    override fun getItemCount(): Int = userList.size
}

// 3. 在Activity中使用
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        recyclerView.layoutManager = LinearLayoutManager(this)
        
        val userList = listOf(
            User(1, "张三", "zhangsan@example.com"),
            User(2, "李四", "lisi@example.com"),
            User(3, "王五", "wangwu@example.com")
        )
        
        val adapter = UserAdapter(userList)
        recyclerView.adapter = adapter
    }
}

3.3 自定义View

当标准组件无法满足需求时,可以创建自定义View。

// 创建自定义View:圆形进度条
class CircleProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    
    private var progress = 0
    private var maxProgress = 100
    private var progressColor = Color.BLUE
    private var backgroundColor = Color.LTGRAY
    
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val rectF = RectF()
    
    init {
        // 读取自定义属性
        val typedArray = context.obtainStyledAttributes(
            attrs,
            R.styleable.CircleProgressView,
            defStyleAttr,
            0
        )
        
        progress = typedArray.getInteger(R.styleable.CircleProgressView_progress, 0)
        maxProgress = typedArray.getInteger(R.styleable.CircleProgressView_maxProgress, 100)
        progressColor = typedArray.getColor(R.styleable.CircleProgressView_progressColor, Color.BLUE)
        backgroundColor = typedArray.getColor(R.styleable.CircleProgressView_backgroundColor, Color.LTGRAY)
        
        typedArray.recycle()
    }
    
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        
        val centerX = width / 2f
        val centerY = height / 2f
        val radius = min(centerX, centerY) - paint.strokeWidth / 2
        
        // 绘制背景圆
        paint.color = backgroundColor
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 20f
        canvas.drawCircle(centerX, centerY, radius, paint)
        
        // 绘制进度圆弧
        paint.color = progressColor
        val sweepAngle = (progress.toFloat() / maxProgress) * 360f
        rectF.set(
            centerX - radius,
            centerY - radius,
            centerX + radius,
            centerY + radius
        )
        canvas.drawArc(rectF, -90f, sweepAngle, false, paint)
        
        // 绘制中心文字
        paint.style = Paint.Style.FILL
        paint.textSize = 40f
        paint.textAlign = Paint.Align.CENTER
        val text = "$progress%"
        canvas.drawText(text, centerX, centerY + paint.textSize / 3, paint)
    }
    
    fun setProgress(newProgress: Int) {
        progress = newProgress.coerceIn(0, maxProgress)
        invalidate() // 触发重绘
    }
}

第四部分:数据存储与网络

4.1 SharedPreferences存储

SharedPreferences是Android中轻量级的键值对存储方案。

class SharedPreferencesManager(context: Context) {
    private val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
    
    companion object {
        private const val KEY_USER_NAME = "user_name"
        private const val KEY_USER_AGE = "user_age"
        private const val KEY_IS_LOGGED_IN = "is_logged_in"
    }
    
    fun saveUserName(name: String) {
        prefs.edit().putString(KEY_USER_NAME, name).apply()
    }
    
    fun getUserName(): String {
        return prefs.getString(KEY_USER_NAME, "") ?: ""
    }
    
    fun saveUserAge(age: Int) {
        prefs.edit().putInt(KEY_USER_AGE, age).apply()
    }
    
    fun getUserAge(): Int {
        return prefs.getInt(KEY_USER_AGE, 0)
    }
    
    fun setLoggedIn(isLoggedIn: Boolean) {
        prefs.edit().putBoolean(KEY_IS_LOGGED_IN, isLoggedIn).apply()
    }
    
    fun isLoggedIn(): Boolean {
        return prefs.getBoolean(KEY_IS_LOGGED_IN, false)
    }
    
    fun clearAll() {
        prefs.edit().clear().apply()
    }
}

4.2 Room数据库

Room是Google推荐的SQLite封装库,提供了编译时SQL验证和类型安全。

// 1. 定义实体类
@Entity(tableName = "users")
data class UserEntity(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val name: String,
    val email: String,
    @ColumnInfo(name = "created_at")
    val createdAt: Long = System.currentTimeMillis()
)

// 2. 定义DAO(数据访问对象)
@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun getAll(): List<UserEntity>
    
    @Query("SELECT * FROM users WHERE id = :userId")
    fun getUserById(userId: Int): UserEntity?
    
    @Insert
    fun insert(user: UserEntity)
    
    @Update
    fun update(user: UserEntity)
    
    @Delete
    fun delete(user: UserEntity)
    
    @Query("DELETE FROM users")
    fun deleteAll()
}

// 3. 定义数据库
@Database(entities = [UserEntity::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
            }
        }
    }
}

// 4. 在ViewModel中使用
class UserViewModel(application: Application) : AndroidViewModel(application) {
    private val userDao = AppDatabase.getDatabase(application).userDao()
    
    val allUsers: LiveData<List<UserEntity>> = userDao.getAll().asLiveData()
    
    fun insert(user: UserEntity) {
        viewModelScope.launch(Dispatchers.IO) {
            userDao.insert(user)
        }
    }
}

4.3 Retrofit网络请求

Retrofit是目前最流行的Android网络请求库,基于OkHttp。

// 1. 定义API接口
interface ApiService {
    @GET("users/{id}")
    suspend fun getUserById(@Path("id") userId: Int): Response<User>
    
    @POST("users")
    suspend fun createUser(@Body user: User): Response<User>
    
    @GET("posts")
    suspend fun getPosts(): List<Post>
}

// 2. 创建Retrofit实例
object RetrofitClient {
    private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
    
    private val okHttpClient = OkHttpClient.Builder()
        .addInterceptor(HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        })
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build()
    
    val instance: ApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

// 3. 在协程中使用
class UserRepository {
    suspend fun getUser(userId: Int): Result<User> {
        return try {
            val response = RetrofitClient.instance.getUserById(userId)
            if (response.isSuccessful) {
                response.body()?.let {
                    Result.success(it)
                } ?: Result.failure(Exception("Empty response"))
            } else {
                Result.failure(Exception("HTTP error: ${response.code()}"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}

// 4. 在ViewModel中调用
class UserViewModel : ViewModel() {
    private val repository = UserRepository()
    
    private val _userState = MutableStateFlow<UserState>(UserState.Loading)
    val userState: StateFlow<UserState> = _userState
    
    fun fetchUser(userId: Int) {
        viewModelScope.launch {
            _userState.value = UserState.Loading
            val result = repository.getUser(userId)
            _userState.value = when (result) {
                is Result.Success -> UserState.Success(result.data)
                is Result.Failure -> UserState.Error(result.exception.message ?: "Unknown error")
            }
        }
    }
}

sealed class UserState {
    object Loading : UserState()
    data class Success(val user: User) : UserState()
    data class Error(val message: String) : UserState()
}

第五部分:高级主题

5.1 Jetpack Compose

Jetpack Compose是Android的现代UI工具包,使用Kotlin声明式编程。

// 1. 基本组件
@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

// 2. 布局组件
@Composable
fun UserProfile(user: User) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        Text(
            text = user.name,
            style = MaterialTheme.typography.h4,
            modifier = Modifier.padding(bottom = 8.dp)
        )
        Text(
            text = user.email,
            style = MaterialTheme.typography.body1,
            color = Color.Gray
        )
        Button(
            onClick = { /* 处理点击 */ },
            modifier = Modifier.padding(top = 16.dp)
        ) {
            Text("编辑资料")
        }
    }
}

// 3. 状态管理
@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }
    
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxWidth()
    ) {
        Text(
            text = "计数: $count",
            style = MaterialTheme.typography.h5,
            modifier = Modifier.padding(16.dp)
        )
        Row(
            modifier = Modifier.padding(8.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Button(onClick = { count++ }) {
                Text("增加")
            }
            Button(onClick = { count-- }) {
                Text("减少")
            }
            Button(onClick = { count = 0 }) {
                Text("重置")
            }
        }
    }
}

// 4. 列表显示
@Composable
fun UserList(users: List<User>) {
    LazyColumn {
        items(users) { user ->
            UserProfile(user = user)
            Divider()
        }
    }
}

// 5. 状态提升(State Hoisting)
@Composable
fun EditableText(
    text: String,
    onTextChange: (String) -> Unit
) {
    TextField(
        value = text,
        onValueChange = onTextChange,
        label = { Text("输入文本") },
        modifier = Modifier.fillMaxWidth()
    )
}

@Composable
fun ParentComponent() {
    var text by remember { mutableStateOf("") }
    
    Column {
        EditableText(
            text = text,
            onTextChange = { newText -> text = newText }
        )
        Text("当前文本: $text")
    }
}

5.2 依赖注入(Dagger Hilt)

依赖注入是管理复杂应用依赖关系的优秀模式。

// 1. 定义模块
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides
    @Singleton
    fun provideApiService(): ApiService {
        return RetrofitClient.instance
    }
    
    @Provides
    @Singleton
    fun provideUserRepository(apiService: ApiService): UserRepository {
        return UserRepository(apiService)
    }
}

// 2. 定义Repository
class UserRepository @Inject constructor(
    private val apiService: ApiService
) {
    suspend fun getUser(userId: Int): User {
        return apiService.getUserById(userId)
    }
}

// 3. 在ViewModel中使用
@HiltViewModel
class UserViewModel @Inject constructor(
    private val userRepository: UserRepository
) : ViewModel() {
    
    private val _user = MutableStateFlow<User?>(null)
    val user: StateFlow<User?> = _user
    
    fun loadUser(userId: Int) {
        viewModelScope.launch {
            _user.value = userRepository.getUser(userId)
        }
    }
}

// 4. 在Activity中使用
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var userRepository: UserRepository
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 使用注入的依赖
        lifecycleScope.launch {
            val user = userRepository.getUser(1)
            // 处理用户数据
        }
    }
}

5.3 性能优化

5.3.1 内存泄漏检测

// 1. 使用LeakCanary检测内存泄漏
// 在build.gradle中添加依赖
// debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'

// 2. 避免常见内存泄漏模式
class MyActivity : AppCompatActivity() {
    private val handler = Handler(Looper.getMainLooper())
    private val runnable = object : Runnable {
        override fun run() {
            // 避免持有Activity引用
            // 使用弱引用或静态内部类
            handler.postDelayed(this, 1000)
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 错误做法:持有Activity引用
        // handler.postDelayed(runnable, 1000)
        
        // 正确做法:使用弱引用
        val weakActivity = WeakReference(this)
        handler.postDelayed(object : Runnable {
            override fun run() {
                weakActivity.get()?.let { activity ->
                    // 使用activity
                }
                handler.postDelayed(this, 1000)
            }
        }, 1000)
    }
    
    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacks(runnable)
    }
}

5.3.2 布局优化

// 1. 使用ConstraintLayout减少嵌套
// 2. 使用ViewStub延迟加载
// 3. 使用RecyclerView的优化技巧

// RecyclerView优化示例
class OptimizedAdapter : RecyclerView.Adapter<OptimizedAdapter.ViewHolder>() {
    // 使用DiffUtil进行高效更新
    private val diffCallback = object : DiffUtil.ItemCallback<User>() {
        override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem.id == newItem.id
        }
        
        override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem == newItem
        }
    }
    
    private val differ = AsyncListDiffer(this, diffCallback)
    
    fun submitList(list: List<User>) {
        differ.submitList(list)
    }
    
    override fun getItemCount(): Int = differ.currentList.size
    
    // 其他方法...
}

第六部分:实战项目案例

6.1 天气应用开发

6.1.1 项目结构

WeatherApp/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/com/example/weatherapp/
│   │   │   │   ├── data/
│   │   │   │   │   ├── model/
│   │   │   │   │   │   ├── Weather.kt
│   │   │   │   │   │   └── Forecast.kt
│   │   │   │   │   ├── repository/
│   │   │   │   │   │   └── WeatherRepository.kt
│   │   │   │   │   └── api/
│   │   │   │   │       └── WeatherApi.kt
│   │   │   │   ├── ui/
│   │   │   │   │   ├── viewmodel/
│   │   │   │   │   │   └── WeatherViewModel.kt
│   │   │   │   │   └── screen/
│   │   │   │   │       ├── WeatherScreen.kt
│   │   │   │   │       └── ForecastScreen.kt
│   │   │   │   └── MainActivity.kt
│   │   │   └── res/
│   │   └── test/
│   └── build.gradle
└── build.gradle

6.1.2 核心代码实现

// 1. 数据模型
data class Weather(
    val city: String,
    val temperature: Double,
    val condition: String,
    val humidity: Int,
    val windSpeed: Double
)

// 2. API接口
interface WeatherApi {
    @GET("weather")
    suspend fun getCurrentWeather(
        @Query("q") city: String,
        @Query("appid") apiKey: String
    ): Response<WeatherResponse>
}

// 3. Repository
class WeatherRepository(private val api: WeatherApi) {
    suspend fun getWeather(city: String): Result<Weather> {
        return try {
            val response = api.getCurrentWeather(city, "YOUR_API_KEY")
            if (response.isSuccessful) {
                response.body()?.let { weatherResponse ->
                    Result.success(weatherResponse.toWeather())
                } ?: Result.failure(Exception("Empty response"))
            } else {
                Result.failure(Exception("API error: ${response.code()}"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}

// 4. ViewModel
@HiltViewModel
class WeatherViewModel @Inject constructor(
    private val repository: WeatherRepository
) : ViewModel() {
    
    private val _weatherState = MutableStateFlow<WeatherState>(WeatherState.Loading)
    val weatherState: StateFlow<WeatherState> = _weatherState
    
    fun fetchWeather(city: String) {
        viewModelScope.launch {
            _weatherState.value = WeatherState.Loading
            val result = repository.getWeather(city)
            _weatherState.value = when (result) {
                is Result.Success -> WeatherState.Success(result.data)
                is Result.Failure -> WeatherState.Error(result.exception.message ?: "Unknown error")
            }
        }
    }
}

// 5. UI组件(Jetpack Compose)
@Composable
fun WeatherScreen(viewModel: WeatherViewModel) {
    val weatherState by viewModel.weatherState.collectAsState()
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        when (val state = weatherState) {
            is WeatherState.Loading -> {
                CircularProgressIndicator()
            }
            is WeatherState.Success -> {
                WeatherDisplay(weather = state.weather)
            }
            is WeatherState.Error -> {
                Text(
                    text = "Error: ${state.message}",
                    color = Color.Red,
                    style = MaterialTheme.typography.body1
                )
            }
        }
    }
}

@Composable
fun WeatherDisplay(weather: Weather) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
    ) {
        Column(
            modifier = Modifier.padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(
                text = weather.city,
                style = MaterialTheme.typography.h4,
                modifier = Modifier.padding(bottom = 8.dp)
            )
            Text(
                text = "${weather.temperature}°C",
                style = MaterialTheme.typography.h2,
                color = if (weather.temperature > 25) Color.Red else Color.Blue
            )
            Text(
                text = weather.condition,
                style = MaterialTheme.typography.h5,
                modifier = Modifier.padding(vertical = 8.dp)
            )
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                WeatherInfoItem("湿度", "${weather.humidity}%")
                WeatherInfoItem("风速", "${weather.windSpeed} m/s")
            }
        }
    }
}

@Composable
fun WeatherInfoItem(label: String, value: String) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(
            text = label,
            style = MaterialTheme.typography.caption,
            color = Color.Gray
        )
        Text(
            text = value,
            style = MaterialTheme.typography.body1,
            fontWeight = FontWeight.Bold
        )
    }
}

6.2 社交媒体应用开发

6.2.1 功能模块

  • 用户认证(登录/注册)
  • 帖子发布与展示
  • 点赞/评论功能
  • 实时消息通知

6.2.2 关键技术点

// 1. Firebase集成
class FirebaseManager {
    private val auth = Firebase.auth
    private val firestore = Firebase.firestore
    
    // 用户认证
    suspend fun login(email: String, password: String): Result<User> {
        return try {
            val authResult = auth.signInWithEmailAndPassword(email, password).await()
            val user = authResult.user
            if (user != null) {
                Result.success(User(user.uid, user.email ?: ""))
            } else {
                Result.failure(Exception("User not found"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    // 发布帖子
    suspend fun createPost(post: Post): Result<String> {
        return try {
            val documentRef = firestore.collection("posts").document()
            documentRef.set(post).await()
            Result.success(documentRef.id)
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    // 实时监听帖子更新
    fun listenToPosts(callback: (List<Post>) -> Unit) {
        firestore.collection("posts")
            .orderBy("timestamp", Query.Direction.DESCENDING)
            .addSnapshotListener { snapshot, error ->
                if (error != null) {
                    Log.e("Firebase", "Error listening to posts", error)
                    return@addSnapshotListener
                }
                
                val posts = snapshot?.documents?.mapNotNull { doc ->
                    doc.toObject(Post::class.java)?.copy(id = doc.id)
                } ?: emptyList()
                
                callback(posts)
            }
    }
}

// 2. 通知系统
class NotificationManager(private val context: Context) {
    private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) 
        as NotificationManager
    
    fun showNotification(title: String, message: String) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                "social_app_channel",
                "Social App Notifications",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }
        
        val notification = NotificationCompat.Builder(context, "social_app_channel")
            .setSmallIcon(R.drawable.ic_notification)
            .setContentTitle(title)
            .setContentText(message)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setAutoCancel(true)
            .build()
        
        notificationManager.notify(System.currentTimeMillis().toInt(), notification)
    }
}

第七部分:测试与调试

7.1 单元测试

// 1. 测试Repository
class UserRepositoryTest {
    private lateinit var userRepository: UserRepository
    private lateinit var mockApi: ApiService
    
    @Before
    fun setup() {
        mockApi = mockk()
        userRepository = UserRepository(mockApi)
    }
    
    @Test
    fun `getUser should return success when API call is successful`() = runTest {
        // Given
        val expectedUser = User(1, "Test User", "test@example.com")
        coEvery { mockApi.getUserById(1) } returns expectedUser
        
        // When
        val result = userRepository.getUser(1)
        
        // Then
        assertTrue(result.isSuccess)
        assertEquals(expectedUser, result.getOrNull())
    }
    
    @Test
    fun `getUser should return failure when API call fails`() = runTest {
        // Given
        coEvery { mockApi.getUserById(1) } throws Exception("Network error")
        
        // When
        val result = userRepository.getUser(1)
        
        // Then
        assertTrue(result.isFailure)
        assertEquals("Network error", result.exceptionOrNull()?.message)
    }
}

// 2. 测试ViewModel
class UserViewModelTest {
    private lateinit var viewModel: UserViewModel
    private lateinit var mockRepository: UserRepository
    
    @Before
    fun setup() {
        mockRepository = mockk()
        viewModel = UserViewModel(mockRepository)
    }
    
    @Test
    fun `fetchUser should update state to success`() = runTest {
        // Given
        val expectedUser = User(1, "Test", "test@example.com")
        coEvery { mockRepository.getUser(1) } returns Result.success(expectedUser)
        
        // When
        viewModel.fetchUser(1)
        
        // Then
        val state = viewModel.userState.first()
        assertTrue(state is UserState.Success)
        assertEquals(expectedUser, (state as UserState.Success).user)
    }
}

7.2 UI测试

// 1. Espresso测试
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)
    
    @Test
    fun testLoginButton() {
        // 点击登录按钮
        onView(withId(R.id.loginButton)).perform(click())
        
        // 验证是否跳转到登录页面
        onView(withId(R.id.loginScreen)).check(matches(isDisplayed()))
    }
    
    @Test
    fun testRecyclerViewDisplay() {
        // 验证RecyclerView是否显示
        onView(withId(R.id.recyclerView)).check(matches(isDisplayed()))
        
        // 验证RecyclerView是否有项目
        onView(withId(R.id.recyclerView)).check(matches(hasChildCount(greaterThan(0))))
    }
}

// 2. Compose UI测试
@HiltAndroidTest
class WeatherScreenTest {
    @get:Rule
    val hiltRule = HiltAndroidRule(this)
    
    @Test
    fun testWeatherScreenLoading() {
        val viewModel = WeatherViewModel(mockRepository)
        viewModel._weatherState.value = WeatherState.Loading
        
        composeTestRule.setContent {
            WeatherScreen(viewModel = viewModel)
        }
        
        composeTestRule.onNodeWithText("Loading...").assertIsDisplayed()
    }
}

第八部分:发布与优化

8.1 应用签名与发布

// 1. 生成签名密钥
// 使用Android Studio的Generate Signed Bundle/APK向导
// 或使用命令行:
// keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-alias

// 2. 配置build.gradle
android {
    signingConfigs {
        release {
            storeFile file("my-release-key.jks")
            storePassword "your-password"
            keyAlias "my-key-alias"
            keyPassword "your-key-password"
        }
    }
    
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

8.2 性能监控

// 1. 使用Firebase Performance Monitoring
class PerformanceMonitor {
    fun trackScreenLoad(screenName: String) {
        val trace = Firebase.performance.newTrace("screen_load_$screenName")
        trace.start()
        
        // 模拟屏幕加载
        Handler(Looper.getMainLooper()).postDelayed({
            trace.stop()
        }, 1000)
    }
    
    fun trackNetworkRequest(url: String) {
        val trace = Firebase.performance.newTrace("network_request")
        trace.putAttribute("url", url)
        trace.start()
        
        // 网络请求完成后停止
        // trace.stop()
    }
}

// 2. 使用Android Profiler
// 在Android Studio中,点击View > Tool Windows > Profiler
// 可以查看CPU、内存、网络使用情况

第九部分:常见问题与解决方案

9.1 内存泄漏

问题: Activity被持有导致无法回收

解决方案:

// 使用弱引用
class MyActivity : AppCompatActivity() {
    private val weakActivity = WeakReference(this)
    
    private val callback = object : SomeCallback {
        override fun onEvent() {
            weakActivity.get()?.let { activity ->
                // 安全使用activity
            }
        }
    }
    
    // 或者在onDestroy中清理
    override fun onDestroy() {
        super.onDestroy()
        // 移除所有监听器和回调
        someManager.removeListener(callback)
    }
}

9.2 网络请求超时

问题: 网络请求在弱网络环境下超时

解决方案:

// 1. 设置合理的超时时间
val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .writeTimeout(30, TimeUnit.SECONDS)
    .build()

// 2. 添加重试机制
class RetryInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        var response: Response? = null
        var exception: IOException? = null
        
        for (i in 0 until 3) { // 最多重试3次
            try {
                response = chain.proceed(request)
                if (response.isSuccessful) {
                    return response
                }
            } catch (e: IOException) {
                exception = e
                if (i < 2) {
                    // 等待一段时间后重试
                    Thread.sleep(1000 * (i + 1).toLong())
                }
            }
        }
        
        throw exception ?: IOException("Max retries exceeded")
    }
}

9.3 界面卡顿

问题: 主线程执行耗时操作导致ANR

解决方案:

// 1. 使用协程处理异步操作
class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch(Dispatchers.IO) {
            // 耗时操作在后台线程执行
            val data = repository.getData()
            
            // 更新UI在主线程
            withContext(Dispatchers.Main) {
                _uiState.value = UiState.Success(data)
            }
        }
    }
}

// 2. 使用WorkManager处理后台任务
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        // 执行耗时操作
        return Result.success()
    }
}

// 安排工作
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
    .setConstraints(Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build())
    .build()

WorkManager.getInstance(context).enqueue(workRequest)

第十部分:进阶学习路径

10.1 推荐学习资源

  1. 官方文档: Android开发者官网
  2. Kotlin官方文档: Kotlin Docs
  3. Jetpack Compose官方教程: Compose Tutorial
  4. Android Architecture Components: 官方指南

10.2 开源项目参考

  1. Android Architecture Blueprints: Google官方的架构示例
  2. Now in Android: Google的Jetpack Compose示例应用
  3. Sunflower: Google的园艺应用示例
  4. iosched: Google I/O会议应用

10.3 社区与论坛

  1. Stack Overflow: 问题解答
  2. Reddit r/androiddev: 社区讨论
  3. Android Developers Discord: 实时交流
  4. GitHub Issues: 开源项目问题跟踪

总结

本指南通过系统性的讲解和丰富的实战案例,涵盖了Android开发从入门到精通的完整知识体系。关键要点包括:

  1. 基础扎实: 深入理解Activity生命周期、Fragment、Intent等核心概念
  2. 现代开发: 掌握Jetpack Compose、Kotlin协程、依赖注入等现代技术
  3. 架构清晰: 采用MVVM架构,分离关注点,提高代码可维护性
  4. 性能优化: 关注内存管理、布局优化、网络请求效率
  5. 测试驱动: 编写单元测试和UI测试,保证代码质量
  6. 持续学习: 关注Android生态发展,不断更新知识体系

Android开发是一个持续学习的过程,建议通过实际项目不断实践,参与开源社区,关注技术动态,逐步成长为一名优秀的Android开发者。