深入分析 Android Activity (十一)

news2025/1/19 17:23:28

文章目录

    • 深入分析 Android Activity (十一)
    • 1. Activity 的内存管理和优化
      • 1.1 内存泄漏的常见原因
      • 1.2 避免内存泄漏的方法
      • 1.3 内存泄漏检测工具
    • 2. Activity 的配置变更处理
      • 2.1 处理配置变更
      • 2.2 保存和恢复状态
      • 2.3 使用 ViewModel
    • 3. Activity 的测试
      • 3.1 单元测试
      • 3.2 UI 测试
    • 4. Activity 与 Fragment 的关系
      • 4.1 添加 Fragment
      • 4.2 处理 Fragment 生命周期
      • 4.3 Fragment 之间的通信
    • 总结

深入分析 Android Activity (十一)

1. Activity 的内存管理和优化

内存管理是 Android 开发中非常重要的一部分。内存泄漏会导致应用崩溃和性能问题,因此需要在开发过程中注意内存管理和优化。

1.1 内存泄漏的常见原因

  • 静态引用:静态变量持有 Activity 的引用会导致内存泄漏。
  • 未取消的监听器:忘记注销注册的监听器或回调会导致内存泄漏。
  • Handler 内存泄漏:匿名内部类 Handler 引用外部类实例,会导致外部类无法被回收。
  • 长时间运行的线程:线程持有 Activity 的引用,在 Activity 销毁后线程未终止,会导致内存泄漏。

1.2 避免内存泄漏的方法

  • 使用弱引用:使用 WeakReference 持有 Activity 的引用。
  • 及时取消监听器和回调:在 onDestroy 或其他适当时机取消监听器和回调。
  • 静态内部类:使用静态内部类避免持有外部类的引用。
  • 使用 Application Context:在适当场景下使用 Application Context 而非 Activity Context。
// 使用 WeakReference 避免内存泄漏
private static class MyHandler extends Handler {
    private final WeakReference<MyActivity> mActivity;

    public MyHandler(MyActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        MyActivity activity = mActivity.get();
        if (activity != null) {
            // Handle message
        }
    }
}

1.3 内存泄漏检测工具

  • LeakCanary:一个内存泄漏检测工具,可以帮助检测内存泄漏。
// 在 Application 类中初始化 LeakCanary
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return;
        }
        LeakCanary.install(this);
    }
}

2. Activity 的配置变更处理

配置变更(如屏幕旋转、语言切换)会导致 Activity 被销毁和重建,需要妥善处理以保存和恢复数据。

2.1 处理配置变更

可以在 AndroidManifest.xml 中通过 android:configChanges 属性指定处理配置变更。

<activity android:name=".MyActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"/>

在 Activity 中重写 onConfigurationChanged 方法。

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // Handle orientation change to landscape
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Handle orientation change to portrait
    }
}

2.2 保存和恢复状态

在配置变更时,可以通过 onSaveInstanceStateonRestoreInstanceState 方法保存和恢复数据。

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("key", "value");
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState != null) {
        String value = savedInstanceState.getString("key");
    }
}

2.3 使用 ViewModel

可以使用 ViewModel 在配置变更期间保存 UI 相关数据。

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> data;

    public LiveData<String> getData() {
        if (data == null) {
            data = new MutableLiveData<>();
            loadData();
        }
        return data;
    }

    private void loadData() {
        // Load data asynchronously
    }
}

// 在 Activity 中使用 ViewModel
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getData().observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        // Update UI
    }
});

3. Activity 的测试

测试是确保应用质量的重要步骤,包括单元测试和 UI 测试。

3.1 单元测试

可以使用 JUnit 进行单元测试。

// 使用 JUnit 测试 Activity 中的方法
@RunWith(AndroidJUnit4.class)
public class MyActivityTest {

    @Test
    public void testActivityMethod() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        assertEquals("com.example.myapp", appContext.getPackageName());
    }
}

3.2 UI 测试

可以使用 Espresso 进行 UI 测试。

// 使用 Espresso 进行 UI 测试
@RunWith(AndroidJUnit4.class)
public class MyActivityUITest {

    @Rule
    public ActivityScenarioRule<MyActivity> activityScenarioRule = new ActivityScenarioRule<>(MyActivity.class);

    @Test
    public void testButtonClick() {
        onView(withId(R.id.my_button)).perform(click());
        onView(withId(R.id.my_text_view)).check(matches(withText("Button clicked")));
    }
}

4. Activity 与 Fragment 的关系

Fragment 是在 Activity 中的可重用组件,用于实现灵活的 UI 设计。

4.1 添加 Fragment

可以在 XML 布局文件中添加 Fragment,也可以在代码中动态添加。

<!-- 在 XML 布局文件中添加 Fragment -->
<fragment
    android:id="@+id/my_fragment"
    android:name="com.example.MyFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
// 在代码中动态添加 Fragment
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment = new MyFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

4.2 处理 Fragment 生命周期

Fragment 的生命周期与 Activity 类似,但有自己独特的生命周期方法。

public class MyFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Fragment 被添加到 Activity 时调用
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Fragment 初始化时调用
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 为 Fragment 创建视图时调用
        return inflater.inflate(R.layout.fragment_my, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Activity 的 onCreate 方法返回时调用
    }

    @Override
    public void onStart() {
        super.onStart();
        // Fragment 可见时调用
    }

    @Override
    public void onResume() {
        super.onResume();
        // Fragment 交互时调用
    }

    @Override
    public void onPause() {
        super.onPause();
        // Fragment 不可见时调用
    }

    @Override
    public void onStop() {
        super.onStop();
        // Fragment 停止时调用
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // Fragment 视图被销毁时调用
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Fragment 被销毁时调用
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Fragment 从 Activity 中分离时调用
    }
}

4.3 Fragment 之间的通信

可以使用接口在 Fragment 之间进行通信。

// 定义接口
public interface OnFragmentInteractionListener {
    void onFragmentInteraction(String data);
}

// 在 Fragment 中实现接口
public class MyFragment extends Fragment {
    private OnFragmentInteractionListener mListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    public void someMethod() {
        if (mListener != null) {
            mListener.onFragmentInteraction("Some data");
        }
    }
}

// 在 Activity 中实现接口
public class MyActivity extends AppCompatActivity implements OnFragmentInteractionListener {
    @Override
    public void onFragmentInteraction(String data) {
        // Handle the data from the fragment
    }
}

总结

通过对 Android Activity 的深入理解和灵活应用,可以实现丰富的用户体验和高效的应用程序。理解其生命周期、权限管理、数据传递、动画效果、导航和返回栈管理、资源管理、配置变更处理、视图层次结构、性能优化、内存管理、测试、Service 交互、BroadcastReceiver

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1712165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编译安装Apache httpd服务(LAMP1)

目录 1.初始化设置&#xff0c;将Apache所需软件包传到 /opt 目录下 &#xff08;1&#xff09;关闭防火墙 &#xff08;2&#xff09;上传软件包到/opt目录 2.安装环境依赖包 3.配置软件模块 4.编译及安装 5.优化配置文件路径&#xff0c;并把httpd服务的可执行程序文件…

DDR5芯片系统框图详解

DDR5 SDRAM(双倍数据率五代同步动态随机存取存储器)的功能框图详细展现了其内部结构和各个关键模块,这些模块协同工作以实现高速数据传输和存储管理。以下是主要组成部分的详细介绍: Controller Logic (控制器逻辑)这是DDR5内存系统的大脑,负责接收来自CPU或SoC的指令,解…

怎么从视频中截取图片?这3个视频截图方法超清晰

怎么从视频中截取图片&#xff1f;从视频中截取图片确实是一个不可或缺的技能&#xff0c;特别是在我们想要留住视频中的某个动人瞬间、重要细节或是用于制作海报、封面等场合时。无论是专业的视频编辑人员&#xff0c;还是普通用户&#xff0c;掌握这技巧都能让视频内容得到更…

光缆监测主要功能值得一看

网络资源管理&#xff1a; 设备管理&#xff1a; 测试告警处理&#xff1a; 百度地图&#xff1a; 报表打印&#xff1a; 路由测试数据、路由段数据、路由故障报警统计、当前故障通知情况、路由测试数据、路由段信息。 手机客户端&#xff1a; 通过手机可以访问系统&#x…

为WPF的Grid添加网格边框线

在WPF中使用Grid绘制表格的时候&#xff0c;如果元素较多、排列复杂的话&#xff0c;界面会看起来很糟糕&#xff0c;没有层次&#xff0c;这时用网格或边框线分割各元素&#xff08;标签或单元格&#xff09;将会是页面看起来整齐有条理。 默认没有边框线的如下图所示&#xf…

FuTalk设计周刊-Vol.049

#AI漫谈 热点捕手 1.Gemini Pro1.5及其百万上下文功能现已向所有人开放 Gemini Pro1.5加入视频模态的长上下文功能&#xff0c;AI可以处理更复杂的视频内容。 链接https://aistudio.google.com/app/prompts/new_chat?reftop.aibase.com 2.Figma 2024 Config 大会 6月26-27日…

Java - 当年很流行,现在已经淘汰的 Java 技术,请不要在继续学了!!!

最近这段时间收到了一些读者的私信&#xff0c;问我某个技术要不要学&#xff0c;还有一些在国外的同学竟然对 Java 图形化很感兴趣&#xff0c;还想找这方面的工作。 比较忙&#xff0c;一直没抽出时间去回答这类问题&#xff0c;刚好看到我关注的一位大佬回答过&#xff0c;这…

着色器技术在AI去衣中的魔法般的作用

引言&#xff1a; 在数字图像处理的世界中&#xff0c;AI去衣技术正逐步成为研究的前沿。它利用人工智能的强大能力&#xff0c;实现对图像中衣物的智能识别与处理。在这一过程中&#xff0c;着色器&#xff08;Shader&#xff09;技术扮演了至关重要的角色。本文将深入探讨着色…

笔记-python-map的用法

map()函数 map()是 Python 内置的高阶函数&#xff0c;它接收一个函数 f 和一个 list&#xff0c;并通过把函数 f 依次作用在 list 的每个元素上&#xff0c;得到一个新的 list 并返回。 1、当seq只有一个时&#xff0c;将函数func作用于这个seq的每个元素上&#xff0c;并得到…

性能工具之 Kafka 快速 BenchMark 测试示例

文章目录 一、什么是 Kafka&#xff1f;二、 Benchmark 测试工具三、 Benchmark 测试场景1、生产者基准测试2、消费者基准测试 四、小结 一、什么是 Kafka&#xff1f; 消息队列&#xff08;Message Queue&#xff09;简称 MQ&#xff0c;是一种跨进程的通信机制&#xff0c;通…

【更新】一次“问题反馈”,下定决心做了多约束多目标智能算法的“模板”

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 关注该代码的同学应该清楚&#xff0c;这个代码已经免费更新了两版了&#xff0c;修复和增加了一些约束内容&#xff0c;本次增加蓄电池初始时刻和终止时刻容量一致约束&#xff0c;可别小瞧这么简单的增加约…

视频转换器哪个好?这5个转换方法值得一试

#云南真不愧是动植物王国#去云南的宝子&#xff0c;都忍不住想用视频记录云南的美景。但分享时可能会遇到视频格式问题&#xff0c;影响在不同平台和设备上的播放。 不过别担心&#xff0c;现在有很多免费的视频格式转换软件可以解决这些问题。如果你想知道哪个免费的视频转换…

buuctf_RE

[WMCTF2020]easy_re 简单输入flag 但是下断点后&#xff0c;还没走几步就报错退出了。 确实没有打印的字符串 main函数也看不懂在干嘛 int __cdecl main(int argc, const char **argv, const char **envp) {__int64 v4; // r13char v5; // r12__int64 v6; // rax_QWORD *v7;…

控制台生产厂家生产流程详解

控制台生产厂家的生产流程是一个复杂而精细的过程&#xff0c;它涉及多个环节&#xff0c;从原材料的准备到最终产品的出厂检验&#xff0c;每一步都至关重要。以下是控制台生产厂家的一般生产流程&#xff1a; 厂家会根据客户的需求和市场趋势进行产品设计。设计师会综合考虑控…

基于掩码自注意力机制的白内障手术后视力预测的不完整多模态学习

文章目录 Incomplete Multimodal Learning for Visual Acuity Prediction After Cataract Surgery Using Masked Self-Attention摘要方法实验结果 Incomplete Multimodal Learning for Visual Acuity Prediction After Cataract Surgery Using Masked Self-Attention 摘要 论…

3款免费的电脑录屏软件,总有一款适合你!

在当今信息化的时代&#xff0c;电脑录屏软件已经成为了一种不可或缺的工具。无论是录制游戏精彩瞬间&#xff0c;还是制作教学视频&#xff0c;一款好的录屏软件都能让用户事半功倍。然而&#xff0c;许多用户都难以找到一款合适的免费录屏软件。接下来&#xff0c;本文将介绍…

docker-compose报错

前提条件 1、使用docker-compose之前&#xff0c;一定要安装并且运行Docker 2、拉取镜像之前&#xff0c;一定要配置Docker镜像加速&#xff0c;否则下载特别慢 情况1 docker-compose无法打开 错误信息&#xff1a; cannot open self /usr/local/bin/docker-compose or arch…

据库管理-第196期 实战RDMA(20240528)

数据库管理196期 2024-05-28 数据库管理-第196期 实战RDMA&#xff08;20240528&#xff09;1 环境2 操作系统配置3 配置NVMe over RDMA4 挂载磁盘处理并挂载磁盘&#xff1a; 5 RDMA性能测试6 iSCSI部署7 iSCSI性能测试8 性能对比总结 数据库管理-第196期 实战RDMA&#xff08…

jeecgboot 同一账号只允许一个人登录

1.需求分析 jeecgboot 框架要实现同一个账号只允许一个人登录&#xff0c;就跟游戏账号类似&#xff0c;“我登录了就把你踢下去&#xff0c;你登录了就把我踢下去”&#xff1b;jwt 原理是生成 token 后一段时间内登录都有效&#xff0c;jeecgboot 中 jwt 和 redis 联合使用后…

基于YOLOV8/YOLOV5的远距离停车场车位检测识别系统

摘要&#xff1a; 在本文中深入探讨了基于YOLOv8/v7/v6/v5的停车位检测系统&#xff0c; 开发远距离停车位检测系统对于提高停车效率具有关键作用。。本系统核心采用YOLOv8技术&#xff0c;并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;以便进行性能指标对比。深入解释了YOL…