深入分析 Android Activity (十一)
文章目录
- 深入分析 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);}@Overridepublic void handleMessage(Message msg) {MyActivity activity = mActivity.get();if (activity != null) {// Handle message}}
}
1.3 内存泄漏检测工具
- LeakCanary:一个内存泄漏检测工具,可以帮助检测内存泄漏。
// 在 Application 类中初始化 LeakCanary
public class MyApplication extends Application {@Overridepublic 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 保存和恢复状态
在配置变更时,可以通过 onSaveInstanceState 和 onRestoreInstanceState 方法保存和恢复数据。
@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>() {@Overridepublic void onChanged(String s) {// Update UI}
});
3. Activity 的测试
测试是确保应用质量的重要步骤,包括单元测试和 UI 测试。
3.1 单元测试
可以使用 JUnit 进行单元测试。
// 使用 JUnit 测试 Activity 中的方法
@RunWith(AndroidJUnit4.class)
public class MyActivityTest {@Testpublic 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 {@Rulepublic ActivityScenarioRule<MyActivity> activityScenarioRule = new ActivityScenarioRule<>(MyActivity.class);@Testpublic 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 -->
<fragmentandroid: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 {@Overridepublic void onAttach(Context context) {super.onAttach(context);// Fragment 被添加到 Activity 时调用}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// Fragment 初始化时调用}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// 为 Fragment 创建视图时调用return inflater.inflate(R.layout.fragment_my, container, false);}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);// Activity 的 onCreate 方法返回时调用}@Overridepublic void onStart() {super.onStart();// Fragment 可见时调用}@Overridepublic void onResume() {super.onResume();// Fragment 交互时调用}@Overridepublic void onPause() {super.onPause();// Fragment 不可见时调用}@Overridepublic void onStop() {super.onStop();// Fragment 停止时调用}@Overridepublic void onDestroyView() {super.onDestroyView();// Fragment 视图被销毁时调用}@Overridepublic void onDestroy() {super.onDestroy();// Fragment 被销毁时调用}@Overridepublic 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;@Overridepublic 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 {@Overridepublic void onFragmentInteraction(String data) {// Handle the data from the fragment}
}
总结
通过对 Android Activity 的深入理解和灵活应用,可以实现丰富的用户体验和高效的应用程序。理解其生命周期、权限管理、数据传递、动画效果、导航和返回栈管理、资源管理、配置变更处理、视图层次结构、性能优化、内存管理、测试、Service 交互、BroadcastReceiver
| 欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |

相关文章:
深入分析 Android Activity (十一)
文章目录 深入分析 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…...
go语言切片、数组去重函数SliceUnique 支持所有值是可比较类型的切片或者数组去重
我们在go语言开发的时候经常会需要对切片或者数组进行去重操作, 今天就给大家分享一个切片 或者数组去重的通用函数。 这里提醒大家注意go语言是严格区分数据类型的, 切片slice 和 数组 array是不同的数据类型, 不要混淆!&#x…...
微信小程序实现计算当前位置到目的地的距离
实现方式:使用腾讯位置服务 微信小程序JavaScript SDK | 腾讯位置服务 1.进腾讯位置服务申请key 2.下载sdk 微信小程序JavaScript SDK | 腾讯位置服务 3.微信公众平台添加授权域名 4.代码实现计算 const qqmap require("../../utils/qqmap-wx-jssdk.min.js…...
灵动微单片机洗衣机方案——【软硬件开发支持】
RAMSUN英尚以洗衣机洗涤主驱电机为例,主驱电机和多电机控制首选MM32SPIN0280.灵动微电子能够提供完整的软硬件开发支持,目前方案已经在主流家电厂出货。 洗衣机方案 皮带洗衣机 DD直驱洗衣机 波轮洗衣机 Mini壁挂和桌面洗衣机 洗涤烘干双变频方案 热泵烘…...
EureKa是什么?
Eureka 是一个源于 Netflix 公司的开源项目,主要用于实现服务注册和服务发现的功能。它是构建分布式系统中的微服务架构的一个关键组件。下面是对 Eureka 的解释: 基本概念 Eureka 是基于 REST 的服务,主要用于管理微服务架构中的服务实例的…...
【数据结构】直接选择排序详解!
文章目录 1.直接选择排序 1.直接选择排序 🐧 begin 有可能就是 maxi ,所以交换的时候,要及时更新 maxi 🍎 直接选择排序是不稳定的,例如: 9 [9] 5 [5],排序后,因为直接选择排序是会…...
vue3中的toRaw API
文章目录 什么是toRaw API?为什么需要toRaw?如何使用toRaw?实际应用场景 这两天在写项目的时候,发现了一个之前没用过的api,于是上网查了一下,发现这个api还是挺常用,所以在这记录一下 什么是t…...
接口响应断言-json
json认识JSONPath源码类学习/json串的解析拓展学习 目的:数据返回值校验测试 json认识 json是什么-是一种数据交换格式,举例平时看到的json图2,在使用中查看不方便,会有格式转化的平台,json格式的展示 JSON在线视图…...
全面盘点多模态融合算法及应用场景
关注作者,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕博,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人 多…...
超分论文走读
codeFormer 原始动机 高度不确定性,模糊到高清,存在一对多的映射纹理细节丢失人脸身份信息丢失 模型实现 训练VQGAN 从而得到HQ码本空间作为本文的离散人脸先验。为了降低LQ-HQ映射之间的不确定性,我们设计尽量小的码本空间和尽量短的Code…...
Android ViewPager2 + FragmentStateAdapter 的使用以及问题
场景介绍:在Android业务功能开发的过程中,需要使用到嵌套ViewPage2实现页面切换,这种场景在我们的开发过程中并不少见,大致结构为一个activity包含一个viewPage2,这个viewPage2中存在一个fragment A,fragme…...
FPGA中的乒乓操作
为什么不直接选用一个缓存更大的FIFO而选用乒乓操作为什么乒乓操作可以实现低速处理高速数据乒乓操作适用哪些场景 一、乒乓操作结构 首先先介绍一下乒乓操作的原理,其结构如下: 输入选择单元负责将数据送到数据缓冲模块,然后输出选择单元负…...
gnocchi学习小结
背景 总结gnocchi 4.4版本gnocchi-metricd工作流程 入口 gnocchi.cli.metricd metricd stop after processing metric默认为0,调servicemanager run MetricdServiceManager __init__ 服务逻辑封装到MetricdServiceManager初始化中 主要由MetricProcessor, Met…...
【机器学习】Pandas中to_pickle()函数的介绍与机器学习中的应用
【机器学习】Pandas中to_pickle()函数的介绍和机器学习中的应用 🌈 欢迎莅临我的个人主页👈这里是我深耕Python编程、机器学习和自然语言处理(NLP)领域,并乐于分享知识与经验的小天地!🎇 &#…...
lightning的hook顺序
结果 setup: 训练循环开始前设置数据加载器和模型。 configure_optimizers: 设置优化器和学习率调度器。 on_fit_start: 训练过程开始。 on_train_start: 训练开始。 on_train_epoch_start: 每个训练周期开始。 on_train_batch_start: 每个训练批次开始。 on_before_bac…...
【ARFoundation自学03】AR Point Cloud 点云(参考点标记)功能详解
和平面识别框架一样 1为XR Origin添加AR Point Cloud Manager组件 然后你的ar应用就具备了点云识别功能,就这么简单 2.可视化这些云点 创建一个美术效果的预制体,人家提供了预设模板 然后拖到仓库(ASSETS)创建预制体ÿ…...
x264 码率控制中实现 VBV 算法源码分析
关于 VBV 的解释与原理可以参考x264 码率控制 VBV 原理。 x264中 VBV 算法执行的流程 vbv 参数配置相关函数 x264_param_default函数 功能:编码参数默认设置,关于 vbv的参数的默认设置;函数内vbv相关代码:/* ... */ //代码有删减 param->rc.i_vbv_max_bitrate = 0; par…...
宝兰德入选“鑫智奖·2024金融数据智能运维创新优秀解决方案”榜单
近日,由金科创新社主办、全球金融专业人士协会支持的“2024 鑫智奖第六届金融数据智能优秀解决方案”评选结果正式公布。凭借卓越的技术实力和方案能力,宝兰德「智能全链路性能监控解决方案」从90个参选方案中脱颖而出,荣誉入选“鑫智奖2024金…...
Unity3D雨雪粒子特效(Particle System)
系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、下雨的特效1-1.首先就是创建一个自带的粒子系统,整几张贴图,设置一下就能实现想要的效果了1-2 接着往下看视频效果 👉二、下雪的特效👉三、下雪有积雪的效果3-1 先把控…...
记录使用自定义编辑器做试题识别功能
习惯了将解析写在代码注释,这里就直接上代码啦,里面用到的bxm-ui3组件库是博主基于element-Plus做的,可以通过npm i bxm-ui3自行安装使用 // 识别方法: // dom 当前识别数据所在区域, questionType 当前点击编辑选择的题目类型&a…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 -----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
