
伙计们,今天咱们来唠唠Android开发里最核心、最基础、你躲都躲不过去的玩意儿——Activity。
你可以把整个App想象成一部电影,那一个个Activity就是电影里的不同场景。比如,登录界面是一个场景(LoginActivity),主界面是另一个场景(MainActivity),设置页面又是另一个……它们之间如何丝滑切换,如何传递“剧情”(数据),如何优雅地“杀青”(关闭),就是咱们今天要聊的重点。
说白了,启动和关闭Activity,就是Android开发的“Hello, World!”。但很多人直到项目上线,对它的理解还停留在“复制粘贴”阶段。今天,咱就把它扒个底朝天,让你不仅会用,还知道为啥这么用。
在深入“相亲”(启动)细节之前,你得先了解Activity这位主角的“人生剧本”——生命周期。
简单说,从你点开一个App,到完全退出,一个Activity会经历:创建(onCreate) -> 开始(onStart) -> 恢复(onResume) -> [被其他活动打断,进入暂停(onPause)] -> [如果被完全盖住,进入停止(onStop)] -> 最后被销毁(onDestroy)。
这就像一个人的一天:起床(onCreate)、洗漱完毕准备出门(onStart)、开始工作/玩耍(onResume)、有人找你说话暂停一下(onPause)、去睡个午觉(onStop)、晚上上床彻底睡着(onDestroy)。
为什么这个很重要? 因为你在“启动”和“关闭”Activity时,其实就是在精准地触发这些生命周期回调。数据保存、资源释放、动画控制,全跟这些钩子函数息息相关。搞不清这个,你的App就容易出现“闪退”、“卡顿”、“数据丢失”等幺蛾子。
好了,现在你的MainActivity(好比你的家)已经运行起来了,你怎么从这里出发,去往另一个ProfileActivity(好比相亲对象的家)呢?
姿势一:显式Intent——直球出击,门牌号清晰
“显式”,顾名思义,就是明确告诉系统:“我,要从MainActivity,去往ProfileActivity!” 这需要你知道目标Activity的“门牌号”——也就是它的 .class 文件。
// 在MainActivity中,比如一个按钮的点击事件里
findViewById(R.id.btn_start_profile).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建一个Intent,明确指定起点和终点
Intent intent = new Intent(MainActivity.this, ProfileActivity.class);
// 出发!
startActivity(intent);
}
});
这段代码翻译成人话就是:“意图(Intent)先生,请带我从MainActivity这个家,去往ProfileActivity那个家,这是地址(.class),麻烦你了!”
优点: 简单、直接、高效,是自家App内部跳转的首选。
缺点: 只能跳转自己App内部的Activity,不够灵活。
姿势二:隐式Intent——广播招亲,有缘者来
“隐式”,就比较有意思了。它不指定具体要去谁家,而是发布一个“需求”,比如“我想找一个能处理‘查看图片’动作的地方”。系统就会在所有App中寻找那些声明了自己能处理这个“需求”的Activity。
// 还是在一个点击事件里
findViewById(R.id.btn_view_image).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
// 设置动作,系统预定义的查看动作
intent.setAction(Intent.ACTION_VIEW);
// 设置数据,这里是一个图片的URI
intent.setData(Uri.parse("content://images/my_photo.jpg"));
// 同样出发!
startActivity(intent);
}
});
这段代码的潜台词是:“系统大哥,广播一下,谁家能‘查看(ACTION_VIEW)’这张图片啊?是自家的相册App,还是微信,还是浏览器?你们谁接了这活我就去谁家!”
优点: 极其强大和灵活,可以实现App之间的功能调用。比如分享、打开网页、选择联系人等。
缺点: 不确定性高,如果没找到能处理的App,会崩溃(所以要用
resolveActivity 先判断一下)。
逛完了ProfileActivity,你想回家了,咋关?
方法一:直接按返回键
最简单,系统自动帮你调用了
finish() 方法,关闭当前Activity,回到上一个。
方法二:在代码里主动“分手”
在你的ProfileActivity里,比如一个“返回”按钮的点击事件中:
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 告诉系统:我这个Activity的使命完成了,可以销毁了
finish();
}
});
注意了! 这里有个超级大坑:千万别手动去调用
onDestroy()! 那是生命周期的回调方法,是系统管理的。你该做的事是
finish(),系统自然会根据流程去调用
onPause,
onStop,
onDestroy。这就好比,你不能自己动手把自己的心脏摘了,你得告诉大脑“我想睡觉”,大脑再指挥身体各部分进入休眠。
光说不练假把式,下面我们搞一个完整的例子,把上面说的全都串起来。
场景: MainActivity是“我家”,里面有个按钮“去相亲”,点击后跳转到DateActivity(相亲现场)。在DateActivity,你可以输入“相亲印象”,然后点击“满意”返回,并把印象数据带回家;或者点击“不合适”直接回家。
1. 创建两个Activity:
MainActivity 和
DateActivity。
2. MainActivity的布局 (activity_main.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...>
<TextView
android:text="欢迎来到我的家(MainActivity)"
... />
<Button
android:id="@+id/btn_go_date"
android:text="出发!去相亲!"
... />
<TextView
android:id="@+id/tv_result"
android:text="相亲结果会显示在这里"
... />
</LinearLayout>
3. MainActivity的代码:
这里的关键是,我们用
startActivityForResult 去启动相亲,因为我们需要等一个“结果”。
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE_DATE = 1; // 一个自定义的请求码,用来识别是哪个“任务”回来了
private TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = findViewById(R.id.tv_result);
findViewById(R.id.btn_go_date).setOnClickListener(v -> {
// 显式Intent,直球出击!
Intent intent = new Intent(MainActivity.this, DateActivity.class);
// 启动,并期待一个结果
startActivityForResult(intent, REQUEST_CODE_DATE);
});
}
// 重写这个方法,专门用来接收“相亲”回来的结果
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 先看看是不是我们等的那个“相亲”任务回来了
if (requestCode == REQUEST_CODE_DATE) {
// 再看看结果是“满意”还是“不满意”
if (resultCode == RESULT_OK) {
// 从带回的数据(data)里取出“印象”
String impression = data.getStringExtra("impression");
tvResult.setText("相亲成功!对方印象:" + impression);
} else if (resultCode == RESULT_CANCELED) {
tvResult.setText("哎,相亲失败,对方觉得不合适。");
}
}
}
}
4. DateActivity的布局 (activity_date.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...>
<EditText
android:id="@+id/et_impression"
android:hint="请输入你对对方的印象..."
... />
<Button
android:id="@+id/btn_ok"
android:text="满意,带回印象"
... />
<Button
android:id="@+id/btn_cancel"
android:text="不合适,直接回家"
... />
</LinearLayout>
5. DateActivity的代码:
这里的关键是,如何设置返回的结果和数据。
public class DateActivity extends AppCompatActivity {
private EditText etImpression;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_date);
etImpression = findViewById(R.id.et_impression);
// “满意”按钮
findViewById(R.id.btn_ok).setOnClickListener(v -> {
// 1. 准备一个“回信”的Intent,可以把数据放进去
Intent resultIntent = new Intent();
String impression = etImpression.getText().toString();
resultIntent.putExtra("impression", impression); // 把印象打包
// 2. 设置结果码为“成功”(RESULT_OK),并把回信Intent也捎上
setResult(RESULT_OK, resultIntent);
// 3. 关闭自己,回家!
finish();
});
// “不合适”按钮
findViewById(R.id.btn_cancel).setOnClickListener(v -> {
// 直接设置结果码为“取消”(RESULT_CANCELED),没有数据
setResult(RESULT_CANCELED);
finish();
});
}
}
运行流程:
打开App,进入MainActivity。点击“去相亲”,跳转到DateActivity。在DateActivity,输入“幽默风趣”,点击“满意,带回印象”。DateActivity关闭,自动回到MainActivity。MainActivity的
onActivityResult 被触发,收到结果码
RESULT_OK 和印象数据“幽默风趣”,并显示在TextView上。
看,一个完整的、带有数据交互的Activity启动和关闭流程就完成了!这简直就是一场完美的“数字相亲”。
最后啰嗦一句,也是很多新手会忽略的。在Activity被销毁(
onDestroy)之前,特别是在
onPause 和
onStop 中,一定要记得释放资源。比如停止动画、关闭数据库连接、反注册广播接收器等。不然,你的App就会像一个不爱收拾房间的懒汉,迟早会被系统“房东”因为占用资源过多而“赶出去”(崩溃或被杀后台)。
好了,关于Activity的启动和关闭,咱们今天就聊到这。希望这篇“相亲指南”能让你对Activity有一个更立体、更深刻的认识。记住,理解生命周期,熟练运用显式和隐式Intent,掌握数据回传,你的Android开发之路就已经成功了一半!剩下的,就是不断的练习和踩坑了。加油!