写点什么

第一行代码——Android(三):活动的实践技巧

2020 年 2 月 23 日

第一行代码——Android(三):活动的实践技巧

编者按:本文节选自郭霖著《第一行代码——Android》一书中的部分章节。


活动的最佳实践

你已经掌握了关于活动非常多的知识,不过恐怕离能够完全灵活运用还有一段距离。虽然知识点只有这么多,但运用的技巧却是多种多样的。所以,在这里我准备教你几种关于活动的最佳实践技巧,这些技巧在你以后的开发工作当中将会非常有用。


活动的最佳实践:知晓当前是在哪一个活动

这个技巧将教会你如何根据程序当前的界面就能判断出这是哪一个活动。可能你会觉得挺纳闷的,我自己写的代码怎么会不知道这是哪一个活动呢?很不幸的是,在你真正进入到企业之后,更有可能的是接手一份别人写的代码,因为你刚进公司就正好有一个新项目启动的概率并不高。阅读别人的代码时有一个很头疼的问题,就是当你需要在某个界面上修改一些非常简单的东西时,却半天找不到这个界面对应的活动是哪一个。学会了本节的技巧之后,这对你来说就再也不是难题了。


我们还是在 ActivityTest 项目的基础上修改,首先需要新建一个BaseActivity类。右击 com.example.activitytest 包→New→Java Class,在弹出的窗口出输入 BaseActivity,如图 1 所示。



图 1 创建BaseActivity


注意这里BaseActivity和普通活动的创建方式并不一样,因为我们不需要让BaseActivity在 AndroidManifest.xml 中注册,所以选择创建一个普通的 Java 类就可以了。然后让BaseActivity继承自AppCompatActivity,并重写onCreate()方法,如下所示:


public class BaseActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); }}
复制代码


我们在onCreate()方法中获取了当前实例的类名,并通过 Log 打印了出来。


接下来我们需要让BaseActivity成为 ActivityTest 项目中所有活动的父类。修改 FirstActivity、SecondActivity 和 ThirdActivity 的继承结构,让它们不再继承自AppCompatActivity,而是继承自BaseActivity。而由于BaseActivity又是继承自AppCompatActivity的,所以项目中所有活动的现有功能并不受影响,它们仍然完全继承了 Activity 中的所有特性。


现在重新运行程序,然后通过点击按钮分别进入到 FirstActivity、SecondActivity 和 ThirdActivity 的界面,这时观察 logcat 中的打印信息,如图 2 所示。



图 2 BaseActivity 中的打印日志


现在每当我们进入到一个活动的界面,该活动的类名就会被打印出来,这样我们就可以时时刻刻知晓当前界面对应的是哪一个活动了。


活动的最佳实践:随时随地退出程序

如果目前你手机的界面还停留在 ThirdActivity,你会发现当前想退出程序是非常不方便的,需要连按 3 次 Back 键才行。按 Home 键只是把程序挂起,并没有退出程序。其实这个问题就足以引起你的思考,如果我们的程序需要一个注销或者退出的功能该怎么办呢?必须要有一个随时随地都能退出程序的方案才行。


其实解决思路也很简单,只需要用一个专门的集合类对所有的活动进行管理就可以了,下面我们就来实现一下。


新建一个ActivityCollector类作为活动管理器,代码如下所示:


public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity) { activities.add(activity); }
public static void removeActivity(Activity activity) { activities.remove(activity); }
public static void finishAll() { for (Activity activity : activities) { if (!activity.isFinishing()) { activity.finish(); } } activities.clear(); }
}
复制代码


在活动管理器中,我们通过一个 List 来暂存活动,然后提供了一个addActivity()方法用于向 List 中添加一个活动,提供了一个removeActivity()方法用于从 List 中移除活动,最后提供了一个finishAll()方法用于将 List 中存储的活动全部销毁掉。


接下来修改BaseActivity中的代码,如下所示:


public class BaseActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("BaseActivity", getClass().getSimpleName()); ActivityCollector.addActivity(this); }
@Override protected void onDestroy() { super.onDestroy(); ActivityCollector.removeActivity(this); }
}
复制代码


BaseActivityonCreate()方法中调用了ActivityCollectoraddActivity()方法,表明将当前正在创建的活动添加到活动管理器里。然后在BaseActivity中重写onDestroy()方法,并调用了ActivityCollectorremoveActivity()方法,表明将一个马上要销毁的活动从活动管理器里移除。


从此以后,不管你想在什么地方退出程序,只需要调用ActivityCollector.finishAll()方法就可以了。例如在 ThirdActivity 界面想通过点击按钮直接退出程序,只需将代码改成如下所示:


public class ThirdActivity extends BaseActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("ThirdActivity", "Task id is " + getTaskId()); setContentView(R.layout.third_layout); Button button3 = (Button) findViewById(R.id.button_3); button3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ActivityCollector.finishAll(); } });
}}
复制代码


当然你还可以在销毁所有活动的代码后面再加上杀掉当前进程的代码,以保证程序完全退出,杀掉进程的代码如下所示:


android.os.Process.killProcess(android.os.Process.myPid());
复制代码


其中,killProcess()方法用于杀掉一个进程,它接收一个进程id参数,我们可以通过myPid()方法来获得当前程序的进程id。需要注意的是,killProcess()方法只能用于杀掉当前程序的进程,我们不能使用这个方法去杀掉其他程序。


活动的最佳实践:启动活动的最佳写法

启动活动的方法相信你已经非常熟悉了,首先通过 Intent 构建出当前的“意图”,然后调用startActivity()startActivityForResult()方法将活动启动起来,如果有数据需要从一个活动传递到另一个活动,也可以借助 Intent 来完成。


假设 SecondActivity 中需要用到两个非常重要的字符串参数,在启动 SecondActivity 的时候必须要传递过来,那么我们很容易会写出如下代码:


Intent intent = new Intent(FirstActivity.this, SecondActivity.class);intent.putExtra("param1", "data1");intent.putExtra("param2", "data2");startActivity(intent);
复制代码


这样写是完全正确的,不管是从语法上还是规范上,只是在真正的项目开发中经常会有对接的问题出现。比如 SecondActivity 并不是由你开发的,但现在你负责的部分需要有启动 SecondActivity 这个功能,而你却不清楚启动这个活动需要传递哪些数据。这时无非就有两种办法,一个是你自己去阅读 SecondActivity 中的代码,二是询问负责编写 SecondActivity 的同事。你会不会觉得很麻烦呢?其实只需要换一种写法,就可以轻松解决掉上面的窘境。


修改 SecondActivity 中的代码,如下所示:


public class SecondActivity extends BaseActivity {
public static void actionStart(Context context, String data1, String data2) { Intent intent = new Intent(context, SecondActivity.class); intent.putExtra("param1", data1); intent.putExtra("param2", data2); context.startActivity(intent); } ...}
复制代码


我们在 SecondActivity 中添加了一个actionStart()方法,在这个方法中完成了 Intent 的构建,另外所有 SecondActivity 中需要的数据都是通过actionStart()方法的参数传递过来的,然后把它们存储到 Intent 中,最后调用startActivity()方法启动 SecondActivity。


这样写的好处在哪里呢?最重要的一点就是一目了然,SecondActivity 所需要的数据在方法参数中全部体现出来了,这样即使不用阅读 SecondActivity 中的代码,不去询问负责编写 SecondActivity 的同事,你也可以非常清晰地知道启动 SecondActivity 需要传递哪些数据。另外,这样写还简化了启动活动的代码,现在只需要一行代码就可以启动 SecondActivity,如下所示:


button1.setOnClickListener(new OnClickListener() {    @Override    public void onClick(View v) {        SecondActivity.actionStart(FirstActivity.this, "data1", "data2");    }});
复制代码


养成一个良好的习惯,给你编写的每个活动都添加类似的启动方法,这样不仅可以让启动活动变得非常简单,还可以节省不少你同事过来询问你的时间。


图书简介https://www.ituring.com.cn/book/1841



相关阅读


第一行代码——Android(一):前行必备,如何使用日志工具


第一行代码——Android(二):掌握活动的生命周期


2020 年 2 月 23 日 08:001281

评论

发布
暂无评论
发现更多内容

Redis为什么这么快?

数据君

redis

深入浅出 WebRTC AEC(声学回声消除)

阿里云视频云

WebRTC 音视频会议 音频技术 实时音视频 音视频算法

企业面临大危机,CRM崩溃告急,程序员竟用特殊手段化解危机!

Learun

敏捷开发 CRM

Java“基础-中级-高级”程序员面试大全

Crud的程序员

Java java程序员 java基础

P8架构挑战:七大专题1425页考点,你能成功吗?

小Q

Java 学习 程序员 架构 面试

你可能不用,但你必须要会!面试必备的Java多线程知识点总结(思维导图+源码笔记),已整理成PDF版文档

Java成神之路

Java 程序员 架构 面试 编程语言

开发者,别让自己孤独

阿里巴巴云原生

开源 开发者 云原生 OAM CloudNative

老师讲的真棒!阿里P7级别面试经验总结,终获offer

欢喜学安卓

android 程序员 面试 移动开发

专访 CNCF 大使张磊:让云原生不再是大厂专属

阿里巴巴云原生

开源 开发者 云原生 OAM CloudNative

甲方日常 65

句子

工作 随笔杂谈 日常

JVM调优不知道怎么回答,阿里总结四大模块,学不会就背过来

小Q

Java 学习 架构 面试 JVM

没有它你的DevOps是玩不转的,你信不?

华为云开发者社区

容器 DevOps 微服务

数据库面试要点:关于MySQL数据库千万级数据查询和存储

华为云开发者社区

数据库 sql 存储

了不起!靠技术脱贫,他们只用了短短两年!

华为云开发者社区

人工智能 华为 技术

关于Redis分布式锁这一篇应该是讲的最好的了,赶紧收藏起来

比伯

Java 编程 架构 面试 技术宅

时序数据库DolphinDB与Druid的对比测试

DolphinDB

数据分析 时序数据库 Druid 数据库选择 DolphinDB

开发实践丨用小熊派STM32开发板模拟自动售货机

华为云开发者社区

物联网 小熊派 开发板

阿里P9架构师推荐的Spring领域巅峰之作《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》,带你深入解析Spring架构与设计原理

Java成神之路

Java 程序员 架构 面试 编程语言

得不到提升的开发老鸟,试试这3个方法,让你事半功倍!

Linux服务器开发

程序员 互联网人 后端开发 底层应用开发 Linux服务器开发

只需三步!慢日志去无踪

数据君

数据库

连续肝了好几天,终于把Java面试最重要的必备知识【Spring知识点】总结整理出来了。

Java成神之路

Java 程序员 架构 面试 编程语言

23种设计模式与六大原则看了又忘,忘了又看?是你看的方法不对!

Java成神之路

Java 程序员 架构 面试 编程语言

不满意社区的轮子,我们自创了一套 React Hooks 风格的数据加载方案

LeanCloud

API React Hooks

网咯请求中的 connectTimeout 和 soTimeout

不在调上

终于拿到蚂蚁金服Offer!!!分享一下全程面试题和面试经验!

小Q

Java 学习 编程 架构 面试

电信新报告 | 数字化转型:搁置还是加速?

VoltDB

5G安全 通信 电子信息

2年Java外包经验程序员的逆袭之路,4面阿里斩获P6级offer的面经总结。

Java成神之路

Java 程序员 架构 面试 编程语言

老师讲的真棒!总结2020年最全180道Android岗面试题,Android校招面试指南

欢喜学安卓

android 程序员 面试 移动开发

快速学会!啃完999页Android面试高频宝典,挥泪整理面经

欢喜学安卓

android 程序员 面试 移动开发

英特尔携手德晟达、游密,发布云会议终端解决方案,打造视听新体验

intel001

关于Kubernetes和Docker关系的八个问题

杨明越

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

第一行代码——Android(三):活动的实践技巧-InfoQ