在Android系统中,四大组件是构成Android应用程序的四种核心组件,它们通过与系统交互,实现应用的多样功能。四大组件主要包括:Activity、Service、BroadcastReceiver和 ContentProvider。学习Android应用程序开发Android四大组件是必须要掌握的技能。
本篇文章四大组件之一Activity开始。
1. Activity简介
一个Android应用程序是由一个或多个Activity组成的,每个Activity可以理解为屏幕上的一个窗口,用于绘制界面和接收用户的交互事件。
下图为抖音应用程序的一个画面的截图,红色矩形框内的就是Activity,可以看到Activity里面包含了视频画面、用户头像,点赞图标、评论图标、分享图标、下文的文字描述等,这些图标和文字都是Activity中的基本控件,我们把它叫做View,在后续的章节中我会专门来介绍这些View的使用。
用户可以通过这些图标与抖音应用交互,比如点击收藏图标,点赞图标。
2. Activity的生命周期
2.1 生命周期方法介绍
onCreate()
当Activity首次启动时被调用,只被用调用一次,例如将Activity切换到后台,再重新启动onCreate方法是不会被调用的。 在onCreate方法中我们可以做一些初始化的工作。
onStart()
Activity对用户可见时被调用,对用户可见分为两种: 1.完全可见 2.部分可见,在Activity上方被其它非全面的窗口遮挡。
onResume()
Activity可以用户交互时被调用,在该状态下Activity中的内容是完全可见的。
onPause()
Activity由完全可见转换为部分可见或完全不可见时会被调用,例如我在将Activity切换到后台或是有其它非全屏空余将当前Activity遮挡。
onStop()
当前Activity完全不可见时会被调用。
onDestory()
当前Activity销毁时会被调用,例如在Activity中调用finish()方法,在onDestory中我们可以做一些资源释放的工作。
onRestart()
当前Activity由后台重新切换到前台时即由不可见状态转换为可见状态时会被调用。
Activity启动时它的生命周期是:onCreate()->onStart()->onResume();
Activity切换到后台时它的生命周期是:onPause()->onStop();
Activity从后台切换到前后时它的生命周期是:onRestart()->onStart()->onResume();
Activity销毁时它的生命周期是:onPause()->onStop()->onDestory();
当前Activity为A,启动另一个Activity B时,A和B的生命周期是:
onPause(A)->onCreate(B)->onStart(B)->onRemuse(B)->onStop(A);
2.2 生命周期Demo
接下来 请查看下方demo,Demo工程名称ActivityDemo,demo代码请参考文章结尾链接
通过代码的方式让我们进一步理解Activity的生命周期
新建MainActivity.java
package com.android.activity.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Button mBtnStart;
private Button mImplicitBtnStart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG,"onCreate方法被调用");
mBtnStart = findViewById(R.id.btn_start);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSecondActivity();
}
});
mImplicitBtnStart = findViewById(R.id.btn_start_implicit);
mImplicitBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSecondActivityByImplicit();
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG,"onStart方法被调用");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG,"onResume方法被调用");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG,"onPause方法被调用");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG,"onStop方法被调用");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG,"onDestroy方法被调用");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG,"onRestart方法被调用");
}
private void startSecondActivity(){
Intent intent = new Intent();
intent.setClass(this,SecondActivity.class);
startActivity(intent);
}
private void startSecondActivityByImplicit(){
Intent intent = new Intent("android.intent.action.second");
startActivity(intent);
}
}
新建SecondActivity.java
package com.android.activity.demo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class SecondActivity extends AppCompatActivity {
private static final String TAG = "SecondActivity";
private Button mBtnBack;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_second_activity);
Log.i(TAG,"onCreate方法被调用");
mBtnBack = findViewById(R.id.btn_back);
mBtnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
goBack();
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG,"onStart方法被调用");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG,"onResume方法被调用");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG,"onPause方法被调用");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG,"onStop方法被调用");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG,"onDestroy方法被调用");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG,"onRestart方法被调用");
}
private void goBack(){
finish();
}
}
Demo工程名称ActivityDemo
在AndroidStudio中启动ActivityDemo工程
关于如何配置Android开发环境请参考: juejin.cn/post/750063…
在AndroidStudio Logcat中我们可以看到以下日志
Logcat是Android系统输出日志的工具,我们可以在代码中打印一些日志方便调式程序的时候使用,在AndroidStudio中我们是可以查看代码中输出的日志。
启动MainActivity
MainActivity生命周期方法执行顺序:onCreate() -> onStart() -> onResume()
MainActivity退到后台不可见时
MainActivity生命周期方法执行顺序:onPause() -> onStop()
MainActivity重新回到前台可见时
MainActivity生命周期方法执行顺序:onRestart() -> onStart() -> onResume()
当前MainActivity可见时启动SecondActivity
MainActivity和SecondActivity生命周期方法执行顺序:onPause(MainActivity) -> onCreate(SecondActivity) -> onStart(SecondActivity) -> onResume(SecondActivity) -> onStop(MainActivity)
当前SecondActivity可见返回到MainActivity时
MainActivity和SecondActivity生命周期方法执行顺序:onPause(SecondActivity) -> onRestart(MainActivity) -> onStart(MainActivity) -> onResume(MainActivity) -> onStop(SecondActivity) -> onDestory(SecondActivity)
3. Activity的启动方式
在Android系统中启动Activity一般有两种方式,显示启动和隐式启动
显式启动:通过指定要启动的Activity的类名来启动;
隐式启动:通过设置Intent的action、category或data来让系统找到合适的Activity来启动;
//当前Activity为MainActivity,现在要通过显示启动的方式启动SecondActivity
intent = new Intent();
intent.setClass(this,SecondActivity.class);
startActivity(intent);
//当前Activity为MainActivity,现在要通过隐示启动的方式启动SecondActivity
Intent intent = new Intent("android.intent.action.second");
startActivity(intent);
//AndroidManifest.xml内容
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.second"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
4. Activity之间如何传递数据
在实际的应用开发中,我们经常会遇到在不同的Activity间传送数据,例如在用户列表页面点击其中的某一条用户信息就会跳转到用户详细信息页面,用户详细信息页面显示的用户信息就是通过用户列表页面传递过去的。
我们使用Intent来不同的Activity之间传递数据,先来介绍下什么是Intent
4.1 Intent
Intent用于Android程序中各组件(Activity、BroadcastReceive、Service)的交互,并且可以在组件之间传递数据,分为显式Intent和隐式Intent。
- 显示Intent
在Intent中直接指定要启动Activity,例如下面的代码中SecondActivity就是我们要启动的Activity。
Intent intent = new Intent();
//第一个参数为Context对象,第二个参数为要启动的Activity
intent.setClass(context,SecondActivity.class);
startActivity(intent);
- 隐式Intent
不直接指明启动的目标Activity,而是根据action和category找出合适的目标。通过AndroidMainfest.xml配置各组件的,只有当和同时匹配时,才能响应对应的Intent。如在SecondActivity中配置:
AndroidManifest.xml
<activity android:name=".SecondActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.second"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
//不直接指定要启动的目标Activity,指定Activity的Action,系统会到AndroidManifest.xml中找到
//匹配的Activity 如果存在多个会弹窗让用户选择
Intent intent = new Intent("android.intent.action.second");
startActivity(intent);
4.2 通过Intent传递数据
在AndroidStudio中的某个Activity下 你输入intent.putExtra之后你会看到给你的很多方法提示
我们可以通过这些方法向目标Activity传递参数,第一个参数是传递参数的名称是String类型,第二个参数是要传递的具体值,Android系统为我们提供了多种数据类型有: byte,short,int,long float,double,char,String,boolean及对应的数组,还有Parcelable
(序列化)用于传递自定义对象的数据 后续的文章会介绍。
回到上面举的例子:在UserActivity中准备数据,在UserDetailActivity中接受数据
UserActivity.java
Intent intent = new Intent();
intent.setClass(context,UserDetailActivity.class);
//向目标Activity传递用户名 String类型
intent.putExtra("UserName","XingChen");
//向目标Activity传递用年龄 int类型
intent.putExtra("age",40);
//向目标Activity传递用身高 float类型
intent.putExtra("height",175.1);
startActivity(intent);
UserDetailActivit.java
Intent intent = getIntent();
String userName = intent.getStringExtra("UserName");
int age = intent.getIntExtra("age",20);
float height = intent.getFloatExtra("height",1.0f);
String info = "你的名字是:" + userName + ",年龄:" + age + ",身高:"+ height;
这样我们就拿到了在UserActivity传递的数据了。
代码链接
提取码:fp16