深入分析 Android Activity (五)
深入分析 Android Activity (五)
1. Activity 的进程和线程模型
在 Android 中,Activity
默认在主线程(也称为 UI 线程)中运行。理解进程和线程模型对于开发响应迅速且无阻塞的应用程序至关重要。
1.1 主线程与 UI 操作
所有 UI 操作必须在主线程中执行,以避免并发问题和 UI 不一致性。长时间的操作应在工作线程中完成,并使用主线程处理结果。
// Performing a long-running operation on a background thread
new Thread(new Runnable() {@Overridepublic void run() {// Long-running operationfinal String result = performOperation();// Post result back to the main threadrunOnUiThread(new Runnable() {@Overridepublic void run() {// Update UI with the resulttextView.setText(result);}});}
}).start();
1.2 使用 AsyncTask
AsyncTask
是一种方便的方式,可以在后台线程中执行操作,并在主线程中处理结果。不过,由于其容易导致内存泄漏和其他问题,现在更推荐使用 ExecutorService
或 RxJava
。
private class MyAsyncTask extends AsyncTask<Void, Void, String> {@Overrideprotected String doInBackground(Void... voids) {return performOperation();}@Overrideprotected void onPostExecute(String result) {textView.setText(result);}
}// Execute the AsyncTask
new MyAsyncTask().execute();
1.3 使用 Handler 和 Looper
Handler
和 Looper
提供了一种灵活的方法来管理线程间通信。
// Creating a Handler on the main thread
Handler handler = new Handler(Looper.getMainLooper());// Running code on the main thread
handler.post(new Runnable() {@Overridepublic void run() {// Update UItextView.setText("Updated from background thread");}
});
2. Activity 的内存优化
内存管理是 Android 开发中的一个重要方面,特别是在设备资源有限的情况下。以下是一些常见的内存优化技巧。
2.1 避免内存泄漏
使用弱引用和上下文的短生命周期对象可以避免内存泄漏。避免在 Activity
和 Fragment
中直接引用长生命周期对象,如单例模式。
// Use WeakReference to avoid memory leaks
private static class MyHandler extends Handler {private final WeakReference<MyActivity> mActivity;MyHandler(MyActivity activity) {mActivity = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {MyActivity activity = mActivity.get();if (activity != null) {// Handle message}}
}
2.2 使用内存分析工具
Android Studio 提供了内存分析工具,可以帮助检测和解决内存泄漏。
// Use Android Profiler to detect memory leaks
2.3 优化 Bitmap 使用
Bitmaps 是常见的内存消耗大户。使用适当的压缩和回收策略来优化 Bitmap 使用。
// Decode bitmap with inSampleSize to reduce memory usage
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options);// Recycle bitmap to free memory
bitmap.recycle();
3. Activity 的跨进程通信(IPC)
在 Android 中,跨进程通信通常使用 AIDL(Android Interface Definition Language)、Messenger 或 ContentProvider 来实现。
3.1 使用 AIDL
AIDL 提供了一种定义接口以便在不同进程之间通信的方法。
// IMyAidlInterface.aidl
interface IMyAidlInterface {void performAction();
}
实现 AIDL 接口:
public class MyService extends Service {private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {@Overridepublic void performAction() {// Perform action}};@Overridepublic IBinder onBind(Intent intent) {return mBinder;}
}
在客户端绑定服务:
private IMyAidlInterface mService;private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName className, IBinder service) {mService = IMyAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName className) {mService = null;}
};// Bind to the service
Intent intent = new Intent(this, MyService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
4. 深入理解 Activity 的配置变化处理
配置变化(如屏幕旋转、语言更改等)会导致 Activity
被销毁并重新创建。开发者可以通过重写 onConfigurationChanged
方法来处理特定配置变化,避免 Activity
重新创建。
4.1 在 Manifest 文件中声明配置变化
<activity android:name=".MyActivity"android:configChanges="orientation|screenSize|keyboardHidden">
</activity>
4.2 重写 onConfigurationChanged
方法
@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);// Handle configuration changesif (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {// Handle landscape orientation} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {// Handle portrait orientation}
}
5. Activity 的调试和日志记录
5.1 使用 Logcat
Logcat
是 Android 提供的日志记录工具,开发者可以使用 Log
类来记录调试信息。
// Log debug information
Log.d("MyActivity", "Debug message");// Log error information
Log.e("MyActivity", "Error message", throwable);
5.2 使用调试工具
Android Studio 提供了强大的调试工具,包括断点调试、内存分析、性能分析等。
// Use breakpoints to debug the application
6. Activity 的单元测试和 UI 测试
测试是确保应用程序质量的关键环节,Android 提供了多种测试框架和工具来进行单元测试和 UI 测试。
6.1 使用 JUnit 进行单元测试
JUnit 是一个常用的 Java 单元测试框架,Android 提供了对 JUnit 的支持。
// Example unit test
public class MyActivityTest {@Testpublic void addition_isCorrect() {assertEquals(4, 2 + 2);}
}
6.2 使用 Espresso 进行 UI 测试
Espresso 是一个用于编写 UI 测试的框架。
// Example UI test
@RunWith(AndroidJUnit4.class)
public class MyActivityTest {@Rulepublic ActivityTestRule<MyActivity> activityRule =new ActivityTestRule<>(MyActivity.class);@Testpublic void ensureTextChangesWork() {onView(withId(R.id.editText)).perform(typeText("Hello"), closeSoftKeyboard());onView(withId(R.id.changeTextButton)).perform(click());onView(withId(R.id.textView)).check(matches(withText("Hello")));}
}
总结
深入理解和掌握 Activity
的各个方面,包括其生命周期、内存管理、进程和线程模型、配置变化处理、调试和测试,对于开发高效、稳定和用户友好的 Android 应用程序至关重要。通过不断学习和实践,可以提升应用程序的性能和用户体验,满足不断变化的用户需求。
相关文章:
深入分析 Android Activity (五)
深入分析 Android Activity (五) 1. Activity 的进程和线程模型 在 Android 中,Activity 默认在主线程(也称为 UI 线程)中运行。理解进程和线程模型对于开发响应迅速且无阻塞的应用程序至关重要。 1.1 主线程与 UI 操作 所有 UI 操作必须…...

Kubernetes 应用滚动更新
Kubernetes 应用版本号 在 Kubernetes 里,版本更新使用的不是 API 对象,而是两个命令:kubectl apply 和 kubectl rollout,当然它们也要搭配部署应用所需要的 Deployment、DaemonSet 等 YAML 文件。 在 Kubernetes 里应用都是以 …...

五分钟”手撕“图书管理系统
前言: 图书馆管理系统需要结合JavaSE的绝大部分知识,是一个很好的训练项目。 为了让大家更加方便的查阅与学习,我把代码放开头,供大家查询。 还有对代码的分析,我将以类为单位分开讲解。 目录 全部代码 Main类 Us…...

8个实用网站和软件,收藏起来一定不后悔~
整理了8个日常生活中经常能用得到的网站和软件,收藏起来一定不会后悔~ 1.ZLibrary zh.zlibrary-be.se/这个网站收录了超千万的书籍和文章资源,国内外的各种电子书资源都可以在这里搜索,98%以上都可以在网站内找到,并且支持免费下…...

电商内卷时代,视频号小店凭借一己之力“脱颖而出”
大家好,我是电商笨笨熊 今年618各大电商平台花样百出; 某宝更是直接取消了“预售”,从5月就开始进入618预热期; 不少玩家既开心又难过,市场如此内卷,618确实是个爆发期,但更多的需要不断压低…...

【论文笔记】| 定制化生成PuLID
PuLID: Pure and Lightning ID Customization via Contrastive Alignment ByteDance, arXiv:2404.16022v1 Theme: Customized generation 原文链接:https://arxiv.org/pdf/2404.16022 Main Work 提出了 Pure 和 Lightning ID 定制 (PuLID),这是一种用于…...
P1638 逛画展
题目描述 博览馆正在展出由世上最佳的 𝑚 位画家所画的图画。 游客在购买门票时必须说明两个数字,𝑎 和 𝑏,代表他要看展览中的第 𝑎 幅至第 𝑏 幅画(包含 𝑎,…...
Linux(centos)常用命令
Linux(Centos)常用命令使用说明文档 切换到/home目录下 使用cd命令切换目录,例如: cd /home列出/home目录下的所有文件 使用ls命令列出目录下的文件和子目录,例如: ls /home新建目录dir1 使用mkdir命…...
从入门到精通:掌握Scrapy框架的关键技巧
在当今信息爆炸的时代,获取并利用网络数据成为了许多行业的核心竞争力之一。而作为一名数据分析师、网络研究者或者是信息工作者,要想获取网络上的大量数据,离不开网络爬虫工具的帮助。而Scrapy框架作为Python语言中最为强大的网络爬虫框架之…...
Vue3按顺序调用新增和查询接口
Vue3按顺序调用新增和查询接口 一、前言1、代码 一、前言 如果你想将两个调用接口的操作封装在不同的方法中,你可以考虑将这两个方法分别定义为异步函数,并在需要时依次调用它们。以下是一个示例代码: 1、代码 <template><div>…...
sizeof的了解
32位编译器 qDebug() << "int:" << sizeof(int);qDebug() << "char:" << sizeof(char);qDebug() << "char*:" << sizeof(char*); 字节数: int: 4 char: 1 char*: 4 64位编译器 字节数&#…...
PostgreSQL 教程
## PostgreSQL 教程 ### 1. PostgreSQL 概述 PostgreSQL 是一个开源的对象关系型数据库管理系统(ORDBMS),以其高扩展性和合规性闻名,支持 SQL 和 JSON 查询。 ### 2. 安装与配置 - **下载与安装**:从 PostgreSQL 官方…...

《基于Jmeter的性能测试框架搭建》改进一
《基于Jmeter的性能测试框架搭建》文末笔者提到了不少待改进之处,如下所示。 Grafana性能图表实时展现,测试过程中需实时截图形成测试报告,不够人性化。解决方案:自动生成测试报告并邮件通知。 Grafana性能图表需测试人员实时监控…...
计算机二进制表示和存储各种数据
目录 计算机二进制是什么 计算机中二进制数作用 不同数据的表示和存储 数字 文字 图片 音频 视频 计算机的中数据的显示和存储 计算机二进制是什么 计算机二进制数:计算机里存储的一切都是以二进制的0和1来表示。二进制是计算机使用的数字编码系统&#x…...

玩机社区 - 2024年最美社区源码开源
玩机社区 - 2024年最美社区源码开源 教程源码文档都内置到压缩包了 https://pan.baidu.com/s/1xwcscTne-JMbmKEntiuAuA?pwd78oi...
Linux系统——面试题分享
目录 1.现在给你三百台服务器,你怎么对他们进行管理? 2.简述 raid0 raid1 raid5 三种工作模式的工作原理及特点 2.1RAID 0 ——可以是一块盘和 N 个盘组合 2.2RAID 1 ——只能2块盘,盘的大小可以不一样,以小的为准 2.3RAID 5 …...

谈恋爱没经验?那就来刷谈恋爱经验宝宝吧
❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。2022年度博客之星评选TOP 10🏆,Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作…...

element-ui输入框和多行文字输入框字体不一样解决
element-ui的type"textarea"的字体样式与其他样式不同 <el-input type"textarea"></el-input> <el-input ></el-input>设置: .el-textarea__inner::placeholder {font-family: "Helvetica Neue", Helvetic…...

(Java企业 / 公司项目)配置Linux网络-导入虚拟机
公司给了我一个IP地址 ,提供了一个虚拟机或者自己搭建虚拟机,还有提供登录的账号密码 可以查看我之前的文章 VMware Workstation Pro 17虚拟机超级详细搭建(含redis,nacos,docker, rabbitmq,sentinel&…...

java的unsafe
在Java中,sun.misc.Unsafe 是一个强大且危险的类,它提供了一些直接操作内存、对象和线程的底层功能。这个类通常不鼓励普通开发者使用,因为它绕过了Java语言的一些安全性和内存管理机制,可能会导致难以追踪的错误和安全漏洞。 Un…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...