Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android常见内存泄漏

Android中常见内存泄漏的场景和解决方案详解

作者:Winston -_-

这篇文章主要为大家详细介绍了Android开发中常见内存泄漏场景及其解决方案,内容包括代码示例、原因分析以及最佳实践建议,希望对大家有所帮助

本文讲解Android 开发中常见内存泄漏场景及其解决方案,内容包括代码示例、原因分析以及最佳实践建议。

1. 静态变量导致的内存泄漏

静态变量的生命周期与应用进程一致,如果静态变量持有了对 Activity 或其他大对象的引用,就可能导致内存泄漏。

场景示例

public class MemoryLeakExample {
    // 静态变量持有 Activity 的引用
    private static Context sContext;

    public static void setContext(Context context) {
        sContext = context;
    }
}

如果在 onCreate() 方法中调用了 MemoryLeakExample.setContext(this),即使 Activity 销毁,sContext 仍然持有对 Activity 的引用,导致内存泄漏。

解决方案

修复代码

public class MemoryLeakExample {
    private static Context sContext;

    public static void setContext(Context context) {
        // 使用 ApplicationContext 避免泄漏
        sContext = context.getApplicationContext();
    }
}

2. Handler 导致的内存泄漏

Handler 会隐式持有外部类的引用,导致外部类无法被垃圾回收。

场景示例

public class MainActivity extends AppCompatActivity {
    private final Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            // 处理消息
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler.postDelayed(() -> {
            // 延迟任务
        }, 10000);
    }
}

如果在任务执行前 Activity 被销毁,Handler 仍然持有对 Activity 的引用。

解决方案

修复代码

public class MainActivity extends AppCompatActivity {
    private static class MyHandler extends Handler {
        private final WeakReference activityReference;

        public MyHandler(MainActivity activity) {
            super(Looper.getMainLooper());
            activityReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            MainActivity activity = activityReference.get();
            if (activity != null) {
                // 处理消息
            }
        }
    }

    private final MyHandler handler = new MyHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler.postDelayed(() -> {
            // 延迟任务
        }, 10000);
    }
}

3. 非静态内部类持有外部类的引用

非静态内部类会隐式持有其外部类的引用,如果长时间持有,则可能导致内存泄漏。

场景示例

public class MainActivity extends AppCompatActivity {
    private class MyTask extends AsyncTask {
        @Override
        protected Void doInBackground(Void... voids) {
            // 执行异步任务
            return null;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyTask().execute();
    }
}

如果 MyTask 执行时间较长,而 Activity 已销毁,则会导致泄漏。

解决方案

修复代码

public class MainActivity extends AppCompatActivity {
    private static class MyTask extends AsyncTask {
        private final WeakReference activityReference;

        MyTask(MainActivity activity) {
            activityReference = new WeakReference<>(activity);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            // 执行异步任务
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            MainActivity activity = activityReference.get();
            if (activity != null) {
                // 更新 UI
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyTask(this).execute();
    }
}

4. 监听器或回调未正确移除

监听器或回调注册后,如果不及时移除,会导致对象无法释放。

场景示例

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view = findViewById(R.id.my_view);
        view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
            }

            @Override
            public void onViewDetachedFromWindow(View v) {
            }
        });
    }
}

如果未移除 OnAttachStateChangeListener,MainActivity 的引用可能被保留。

解决方案

在适当的生命周期方法中移除监听器或回调。

修复代码

public class MainActivity extends AppCompatActivity {
    private View.OnAttachStateChangeListener listener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view = findViewById(R.id.my_view);
        listener = new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {
            }

            @Override
            public void onViewDetachedFromWindow(View v) {
            }
        };
        view.addOnAttachStateChangeListener(listener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        View view = findViewById(R.id.my_view);
        if (view != null && listener != null) {
            view.removeOnAttachStateChangeListener(listener);
        }
    }
}

5. 单例模式导致的内存泄漏

单例对象的生命周期与应用一致,如果单例持有了对 Context 或 Activity 的引用,就会导致泄漏。

场景示例

public class Singleton {
    private static Singleton instance;
    private Context context;

    private Singleton(Context context) {
        this.context = context;
    }

    public static Singleton getInstance(Context context) {
        if (instance == null) {
            instance = new Singleton(context);
        }
        return instance;
    }
}

在获取 Singleton 时传入了 Activity 的 Context,会导致泄漏。

解决方案

修复代码

public class Singleton {
    private static Singleton instance;
    private Context context;

    private Singleton(Context context) {
        // 使用 ApplicationContext 避免泄漏
        this.context = context.getApplicationContext();
    }

    public static Singleton getInstance(Context context) {
        if (instance == null) {
            instance = new Singleton(context);
        }
        return instance;
    }
}

6. 其他常见场景

6.1 Bitmap 未及时回收

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image);
// 使用完毕后应回收
bitmap.recycle();

6.2 WebView 泄漏

WebView webView = new WebView(context);
webView.destroy();

以上示例涵盖了 Android 中常见的内存泄漏场景及其解决方法,通过合理使用静态类、弱引用以及生命周期管理,可以有效减少内存泄漏问题。

到此这篇关于Android中常见内存泄漏的场景和解决方案详解的文章就介绍到这了,更多相关Android常见内存泄漏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文