android——开发中的常见Bug汇总与解决方案(闪退)

Android开发中的常见Bug汇总与解决方案

引言

作为一名Android开发者,在日常开发中难免会遇到各种奇怪的bug。有些bug一闪而过,有些则让人抓狂数小时。今天我将系统性地汇总Android开发中常见的bug类型,并提供解决方案,希望能帮助大家少走弯路。

一、闪退类Bug(Crash)

1.1 空指针异常(NullPointerException)

**出现频率:** ★★★★★

```java

// 常见场景1:未初始化直接使用

String text = null;

Log.d("TAG", text.length()); // Crash!

// 常见场景2:从Bundle/Intent中获取数据

String data = getIntent().getStringExtra("key");

if (data.equals("value")) { // 可能为null

// ...

}

// 解决方案:

// 1. 使用Objects.requireNonNull()进行显式检查

// 2. 使用Optional类(Java 8+)

// 3. 启用Kotlin的空安全特性

```

1.2 数组越界(ArrayIndexOutOfBoundsException)

```java

// 常见场景:

String[] array = new String[5];

String item = array[5]; // 索引0-4,5越界

// 解决方案:

// 1. 始终检查数组长度

// 2. 使用增强for循环

for (String item : array) {

// 安全遍历

}

```

1.3 内存不足(OutOfMemoryError)

**触发场景:**

  • 加载大尺寸图片未压缩

  • Activity/Fragment内存泄漏

  • 大量数据缓存未清理

**解决方案:**

```kotlin
// 1. 使用图片加载库(Glide/Picasso)的缓存机制

Glide.with(context)

.load(url)

.diskCacheStrategy(DiskCacheStrategy.ALL)

.into(imageView)

// 2. 及时释放资源

override fun onDestroy() {

super.onDestroy()

// 取消网络请求

// 清空大对象引用

// 移除回调监听

}

```

未释放资源导致点击应用立马闪退,日志里面什么都没有报

具体代码是:

复制代码
private final NLDeviceStream ds = new NLDevice(NLDeviceStream.DevClass.DEV_CDC);

原因:以上代码只使用open打开io来使用,未在适当的时候进行释放导致的立马闪退。

应该在ondestroy释放

复制代码
if (ds.isOpen()) {
    try {
        ds.close();
    } catch (Exception e) {
        LogRyb.INSTANCE.write("【ReplenishActivity】ds的close异常"+e.getMessage());
    }
}

二、界面显示异常

2.1 布局错乱/重叠

**常见原因:**

  • 不同屏幕尺寸适配问题

  • ConstraintLayout约束冲突

  • RelativeLayout依赖关系循环

**解决技巧:**

```xml

<!-- 使用百分比布局 -->

<androidx.percentlayout.widget.PercentFrameLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

<ImageView

app:layout_widthPercent="50%"

app:layout_heightPercent="50%" />

</androidx.percentlayout.widget.PercentFrameLayout>

<!-- 使用SafeArea处理刘海屏 -->

<androidx.constraintlayout.widget.ConstraintLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:fitsSystemWindows="true">

```

2.2 RecyclerView显示异常

```java

// Bug 1: 数据更新但UI不刷新

adapter.notifyDataSetChanged(); // 正确方式

// Bug 2: 图片闪烁/重复

@Override

public void onBindViewHolder(ViewHolder holder, int position) {

// 必须清除旧数据!

holder.imageView.setImageDrawable(null);

loadImage(position, holder.imageView);

}

// Bug 3: 滚动卡顿

// 解决方案:使用DiffUtil增量更新

public class MyDiffCallback extends DiffUtil.Callback {

// 实现比较逻辑

}

```

三、多线程并发问题

3.1 主线程阻塞(ANR)

```java

// 错误示例:在主线程执行耗时操作

new Thread(() -> {

// 网络请求

// 数据库操作

// 文件读写

}).start();

// 正确使用AsyncTask/Loader/RxJava/Coroutine

lifecycleScope.launch {

val data = withContext(Dispatchers.IO) {

// IO操作

}

// 更新UI(自动回到主线程)

updateUI(data)

}

```

3.2 线程安全问题

```kotlin

// 共享变量访问冲突

var count = 0

fun increment() {

// 多线程同时访问会导致数据错误

count++

}

// 解决方案:

// 1. 使用synchronized

@Synchronized

fun safeIncrement() {

count++

}

// 2. 使用Atomic变量

val atomicCount = AtomicInteger(0)

fun atomicIncrement() {

atomicCount.incrementAndGet()

}

```

四、数据存储与解析异常

4.1 数据库操作异常

```java

// 忘记关闭Cursor

Cursor cursor = db.query(...);

// 使用后必须关闭!

cursor.close();

// 使用try-with-resources(API 19+)

try (Cursor cursor = db.query(...)) {

// 自动关闭

}

// Room数据库中的常见问题

@Dao

interface UserDao {

// 返回LiveData或Flow可自动观察数据变化

@Query("SELECT * FROM user")

fun getAll(): LiveData<List<User>>

}

```

4.2 JSON解析异常

```kotlin

// 使用安全的JSON解析库

val json = JSONObject(jsonString)

// 可能抛出JSONException

// 推荐使用Gson/Moshi + try-catch

try {

val user = Gson().fromJson(jsonString, User::class.java)

} catch (e: JsonSyntaxException) {

// 处理解析失败

}

// 或使用Kotlin的扩展函数

fun String.safeToJson(): JsonObject? = try {

JsonParser.parseString(this).asJsonObject

} catch (e: Exception) {

null

}

```

五、网络请求相关Bug

5.1 网络权限缺失

```xml

<!-- 必须声明网络权限 -->

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Android 9+需要额外配置 -->

<application

android:usesCleartextTraffic="true" <!-- 允许HTTP -->

android:networkSecurityConfig="@xml/network_security_config">

```

5.2 请求回调内存泄漏

```java

// 错误:持有Activity引用

api.getData(new Callback() {

@Override

public void onSuccess(Data data) {

// 如果Activity已销毁,这里可能崩溃

activity.updateUI(data);

}

});

// 正确:使用弱引用或Lifecycle

api.getData(new WeakCallback<Activity>(activity) {

@Override

public void onSuccess(Activity ref, Data data) {

if (ref != null && !ref.isDestroyed()) {

ref.updateUI(data);

}

}

});

```

六、兼容性问题

6.1 版本兼容

```java

// 检查系统版本

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

// 使用新API

requestPermissions(permissions, requestCode);

} else {

// 降级处理

}

// 使用兼容库替代

// 例如:使用AppCompatActivity代替Activity

// 使用Fragment代替android.app.Fragment

```

6.2 厂商定制系统Bug

**常见问题:**

  • 后台限制(华为、小米、OPPO等)

  • 通知栏权限

  • 自启动管理

**解决方案:**

```kotlin

// 1. 添加到白名单引导

fun checkBackgroundRestriction(context: Context) {

if (Build.MANUFACTURER.equals("xiaomi", ignoreCase = true)) {

// 引导用户开启自启动

showXiaomiAutoStartGuide()

}

}

// 2. 使用WorkManager处理后台任务

val workRequest = PeriodicWorkRequestBuilder<MyWorker>(

15, TimeUnit.MINUTES

).build()

WorkManager.getInstance(context).enqueue(workRequest)

```

七、调试与预防技巧

7.1 日志记录策略

```kotlin

object AppLogger {

private const val TAG = "MyApp"

fun d(msg: String) {

if (BuildConfig.DEBUG) {

Log.d(TAG, msg)

} else {

// 生产环境:上传到服务器

uploadLogToServer(msg)

}

}

fun crash(throwable: Throwable) {

// 使用Firebase Crashlytics等崩溃统计

FirebaseCrashlytics.getInstance().recordException(throwable)

}

}

```

7.2 单元测试与UI测试

```kotlin

// 单元测试

@Test

fun `test login with valid credentials`() {

val viewModel = LoginViewModel()

viewModel.login("user", "pass123")

assertTrue(viewModel.isLoggedIn.value!!)

}

// UI测试(Espresso)

@RunWith(AndroidJUnit4::class)

class LoginActivityTest {

@Test

fun testLoginButton() {

onView(withId(R.id.login_btn))

.perform(click())

onView(withId(R.id.welcome_text))

.check(matches(isDisplayed()))

}

}

```

7.3 代码审查清单

  • \] 所有外部输入都经过验证

  • \] 网络请求有超时和重试机制

  • \] 敏感信息不硬编码

  • \] 权限申请有拒绝处理

八、常用工具推荐

  1. **LeakCanary** - 内存泄漏检测

  2. **Stetho** - Facebook调试工具

  3. **BlockCanary** - UI卡顿检测

  4. **Android Profiler** - 官方性能分析工具

  5. **Lint** - 代码静态检查

  6. **Firebase Crashlytics** - 崩溃统计

结语

Bug是程序员成长路上的必经之路。面对bug,我们要有:

  1. **耐心** - 仔细分析日志和堆栈信息

  2. **方法论** - 使用二分法、断点调试等技巧

  3. **预防意识** - 编写健壮的代码,添加充分的测试

  4. **学习心态** - 每个bug都是学习的机会

记住:没有不会写bug的程序员,只有不会调试的程序员。希望这份汇总能帮助大家在Android开发路上走得更加顺畅!


**持续更新中...** 如果你有其他常见的bug案例,欢迎在评论区分享!

相关推荐
小小测试开发2 小时前
实战派SQL性能优化:从语法层面攻克项目中的性能瓶颈
android·sql·性能优化
QuantumLeap丶3 小时前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios
StarShip5 小时前
从Activity.setContentView()开始
android
千里马学框架5 小时前
重学SurfaceFlinger之Layer显示区域bounds计算剖析
android·智能手机·sf·安卓framework开发·layer·surfaceflinger·车载开发
nono牛6 小时前
安卓休眠与唤醒流程
android
二流小码农7 小时前
鸿蒙开发:个人开发者如何使用华为账号登录
android·ios·harmonyos
StarShip7 小时前
Android View框架概览
android·计算机图形学
愤怒的代码7 小时前
解析Android内存分析的指标
android·app
summerkissyou19877 小时前
android-hardware/interfaces/automotive和hardware/libhardware/include/hardware区别
android