初识Activity

关于Activity

  1. 可以与用户交互的一个单独的屏幕。

    • 例如:计算器、拨号屏幕等。
  2. Activity用来管理需要显示的各种组件。

    • 例如,按钮、输入框、文本框等等。
  3. 一个应用程序一般由多个Activity构成。

  4. Activity具有生命周期。

创建Activity

创建Activity的方法:

  1. 创建一个继承Activity类或Activity派生类的子类

  2. 实现回调方法onCreadte(),并调用setContentView(int LayoutResID)方法,加载布局文件。

  3. 在AndroidManifest.xml中声明Activity

Activity的派生类

image-20210117161431846

为了方便开发,一般继承AppCompatActivity而不直接继承Activity。

Intent和 IntentFilter 的解析

了解Intent与IntentFilter

什么是Intent

Intent的中文意思是“意向、意图”。Android中提供了Intent机制来协助应用间的交互和应用程序内部的activity, service和broadcast receiver之间的交互。即使用Intent 实现程序的”调用意图”。

Intent包括如下的属性,用于完成执行的意图:

  1. action(动作): 用来表示意图的动作,如:查看,发邮件,打电话

  2. category(类别): 用来表示动作的类别。

  3. data(数据): 表示与动作要操作的数据。如:查看指定的联系人

  4. type(数据类型): 对data类型的描述。

  5. extras(附件信息): 附件信息。如:详细资料,一个文件,某事。

  6. component(目标组件): 目标组件。

什么是IntentFilter

顾名思义,IntentFilter是Intert的过滤器。 Android 操作系统使用过滤器来指定一系列活动、服务和广播接收器处理意图,需要借助于意图所指定的动作、类别、数据模式。

“过滤”大多情况下不在java代码中设置,而是在应用的manifest文件中作为元素的方式声明。在 manifest 文件中使用 元素在活动,服务和广播接收器中列出对应的动作,类别和数据类型。

Activity间的跳转

Intent 调用分为两种:Explicit(显式意图)和 Implicit(隐式意图)

  • Explicit(显式意图):

    显式意图经常用于连接应用程序的内部世界。例如,在一个应用中,需要从一个Activity跳转到另外一个Activity。

  • Implicit(隐式意图):

    隐式意图经常用于激活其他应用程序的组件。例如,启动浏览器打开一个网页,启动拨打电话界面等。

显式Intent跳转Activity

通过名称启动目标组件:

  1. 实例化Intent对象。其中一个Intent构造方法:Intent(Context Context, Class<?> cls)
  2. 调用Activity.startActivity(Intent intent) 方法,启动一个Activity.
1
2
3
4
// 通过指定类名的显式意图
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
// 启动目标活动
startActivity(intent);

隐式Intent启动系统默认浏览器:

当无法确定意图目标,即目标组件名称时,使用隐式Intent启动。通常用于启动其他应用的组件。

1
2
3
4
5
6
//准备Intent的data属性数据
Uri uri = Uri.parse("http://www.baidu.com");
//设置Intent的action属性和data属性
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
//启动目标意图
startActivity(intent);

隐式Intent启动自定义“浏览器”:

向自定义浏览器的AndroidManiFest.xml文件添加过滤器配置

1
2
3
4
5
6
7
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>

在MainAcitivity中获取网页地址

1
2
3
4
//获取Intent对象
Intent intent=getIntent();
//获取intent对象中data属性的字符串数据
String uriStr=intent.getDataString();

直接启动自定义“浏览器”:

1.在自定义浏览器的AndroidManifest.xml中增加过滤器action属性值。

1
2
3
4
5
<intent-filter>
……
<action android:name="com.ncvt.mybrower.start" />
……
</intent-filter>

2.通过自定义浏览器设定的action动作:“com.ncvt.mybrower.start”,直接启动自定义浏览器。

1
2
3
4
//准备Intent的data属性数据
Uri uri = Uri.parse("http://www.baidu.com");
Intent intent = new Intent("com.ncvt.mybrower.start",uri);
startActivity(intent);

Activity的传值

跳转Activity时传递数据

方法一:直接把数据添加到Intent对象

MainActivity启动SecondActivity,传递extra_data

1
2
3
4
5
String data="Hi, SecondActivity";
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
//向intent对象添加数据
intent.putExtra("extra_data ", data );
startActivity(intent);

在SecondActivity接收extra_data

1
2
3
4
//获取Intent对象
Intent intent=getIntent();
//获取传递过来的String类型的数据
String data=intent.getStringExtra("extra_data ");

方法二:把数据添加到Bundle(大篮子)对象

image-20210118160729295

当我们需要连续传递数据或者向多个页面传递数据时,如果采用方法一就会特别繁琐,所以就有了方法二。

Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值。

MainActivity向SecondActivity传递bubdle对象

1
2
3
4
5
6
7
8
9
//实例化bundle对象
Bundle bundle = new Bundle();
//向bundle对象添加数据
bundle.putString("name", "张三" );
bundle.putInt("age", 20);
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
//向intent对象bundle
intent.putExtras(bundle);
startActivity(intent);

在SecondActivity接收bubdle对象

1
2
3
4
5
//获取bundle对象
Bundle bundle = getIntent().getExtras();
//通过key为“name”来获取value即 nameString.
String name=bundle.getString("name");
int age=bundle.getInt("age");

得到Activity返回的数据

startActivityForResult(Intent intent, int requestCode);

setResult(int resultCode, Intent data);

onActivityResult(int requestCode, int resultCode, Intent data);

三个方法间的关系:

1. MainActivity通过调用startActivityForResult()跳转到OtherActivity。

1
2
3
4
5
6
// 返回的结果码
public final static int REQUEST_CODE = 1;
//创建intent对象
Intent intent=new Intent(this,OtherActivity.class);
//启动OtherActivity,并发送请求码
startActivityForResult(intent,REQUEST_CODE);

2. OtherActivity在自己关闭之前,通过setResult()方法返回数据给MainActivity。

1
2
3
4
5
6
7
8
9
EditText editText=findViewById(R.id.editText);
//数据是使用Intent返回
Intent intent = new Intent();
//把返回数据存入Intent
intent.putExtra("result", editText.getText().toString());
//设置返回数据
this.setResult(0,intent);
//关闭当前窗口
this.finish();

3. MainActivity通过复写onActivityResult()方法来取得回传值。

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE:
TextView textView = (TextView) findViewById(R.id.textView2);
textView.setText(data.getStringExtra("result"));
break;
default:
}
}
image-20210118184836920 image-20210118184924435

Activity的生命周期

关于Activity 栈(Task)

Task 就是一个栈 (A task is a stack of activities.) ,这个栈里面存放了很多 Activity ,它遵循着后进先出的原则。 栈有两个动作:进栈(把对象压入到栈当中)和出栈(把栈中的第一个对象从栈里面拿出来)。

关于Activity的生命周期

–Activity在进栈与出栈的过程中,一般意义上有四种状态:

1.当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态

2.当Activity失去了焦点但仍然部分可见(如栈顶的Activity是透明的或者栈顶Activity并不是铺满整个手机屏幕),此时处于暂停状态

3.当Activity被其他Activity完全遮挡,此时此Activity对用户不可见,此时处于停止状态

4.当Activity由于人为或系统原因(如低内存等)被销毁,此时处于销毁状态

Activity的7个回调方法:

1.onCreate() :当Activity第一次被创建时调用,完成活动的初始化操作。

2.onStart() :当用户可以看到这个Activity时调用。

3.onResume() :当获得了用户的焦点时,就是用户点击了屏幕。

4.onPause() :当系统准备启动或回复另一个活动时调用。

5.onStop() :当活动完全不可见时调用,当新启动的活动是对话框式的,还处于可见时,该方法不会被调用。

6.onDestroy():活动被销毁时调用 。

7.onRestart():当活动由停止状态变为运行状态时调用。

image-20210119103651161

Activity的状态:

1.运行状态:在前台、获取了焦点、可以交互

2.暂停状态:部分可见,是去了焦点、无法交互

3.停止状态:不可见、内存中保留Activity对象

4.非活动状态:不在以上三种状态中的Activity则处于非活动状态

image-20210119104914454

Activity的3种生存期:

  1. 完整生命周期:活动在onCreate() 方法和onDestroy()方法之间所经历的,就是完整生命周期。一般情况下,一个活动会在onCreate()方法中完成各种初始化, onDestroy()方法中完成释放资源的操作。

2.前台生命周期:活动在onResume() 方法和onPause()方法之间所经历的就是前台生命周期。在前台生命周期内,活动总是处于运行状态,此时的活动可以与用户进行交互。

3.可视生命周期:活动在 onStart()方法与 onStop()方法之间所经历的,就是可视生命周期。在可视生命周期内,活动对于用户是可见的,但可能无法和用户进行交互。

image-20210119111616477

体验完整生命周期

•启动Activity1后

onCreate()

onStart()

onResume()

•按Back键

onPause()

onStop()

onDestroy()

image-20210119134744612

体验前台生命周期

场景2:启动Activity1后,通过Activity1上的按钮启动Activity2(对话框),Activity1处于休眠,但仍然可见,。在activity声明中添加对话框样式:

android:theme=“@android:style/Theme.AppCompat.Dialog”

image-20210119134729359

体验可视生命周期

场景3:Activity1启动后,启动来电和接听电话界面,将Activity1完全遮挡,然后挂断电话返回Activity1。

image-20210119134614979

Activity的启动模式

关于Activity的种启动模式

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。

Activity启动模式设置:

Activity的四种启动模式:

  1. Standard;
  2. singleTop;
  3. singleTask;
  4. singleInstance

Standard 模式

默认启动模式,每次激活Activity时都会创建Activity,并放入任务栈中

singleTop 模式

如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。

singleTask 模式

如果在栈中已经有该Activity的实例,就重用该实例。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

singleInstance 模式

在一个新栈中创建Activity实例,并让多个应用共享栈中的唯一这个Activity实例。任何应用再激活该Activity时,都会重用该栈中的实例,其效果相当于多个应用程序共享一个Activity。

在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦该模式的Activity的实例存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

小案例:登录模块开发

主界面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/register_bg"
tools:context=".MainActivity">

<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="10dp">

<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Launch Your App"
android:textSize="30sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>

<TextView
android:id="@+id/tv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:layout_marginTop="140dp"
android:textSize="20sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>

<TextView
android:id="@+id/tv_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:layout_marginTop="10dp"
android:textSize="17sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>

<TextView
android:id="@+id/tv_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:layout_marginTop="10dp"
android:textSize="17sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>

<Button
android:id="@+id/btn_start_register"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_bright"
android:textStyle="bold"
android:layout_marginTop="30sp"
android:text="register" />

<Button
android:id="@+id/btn_start_signin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_bright"
android:textStyle="bold"
android:layout_marginTop="10sp"
android:text="sign in" />

</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

注册界面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/register_bg"
tools:context=".RegisterActivity">

<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="10dp">

<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="REGISTER"
android:textSize="30sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>


<EditText
android:id="@+id/et_reg_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:ems="10"
android:hint="Email"
android:maxLines="1"
android:inputType="textEmailAddress"
android:text="" />

<EditText
android:id="@+id/et_reg_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="ID"
android:maxLines="1"
android:inputType="textPersonName"
android:text="" />

<EditText
android:id="@+id/et_reg_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="PassWord"
android:maxLines="1"
android:inputType="textPassword"
android:text="" />

<Button
android:id="@+id/btn_reg_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_bright"
android:textStyle="bold"
android:layout_marginTop="30sp"
android:text="register" />


</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

登陆界面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/register_bg"
tools:context=".SigninActivity">

<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="10dp">

<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sign In"
android:textSize="30sp"
android:textColor="#fff"
android:textStyle="bold"
android:gravity="center"
/>

<EditText
android:id="@+id/et_signin_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="ID"
android:maxLines="1"
android:inputType="textPersonName"
android:text="" />

<EditText
android:id="@+id/et_signin_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="PassWord"
android:maxLines="1"
android:inputType="textPassword"
android:text="" />

<Button
android:id="@+id/btn_signin_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_bright"
android:textStyle="bold"
android:layout_marginTop="30sp"
android:text="sign in" />
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

主界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.example.timeemail;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private static final int REQUEST_REGISTER_CODE=1;
private static final int REQUEST_SIGNIN_CODE=0;

private TextView tvstatus;
private TextView tvemail;
private TextView tvid;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvstatus = (TextView)findViewById(R.id.tv_status);
tvemail = (TextView)findViewById(R.id.tv_email);
tvid = (TextView)findViewById(R.id.tv_id);
}

public void btn_start_signin_onclick(View view) {
Intent intent = new Intent(MainActivity.this,SigninActivity.class);
startActivityForResult(intent,REQUEST_SIGNIN_CODE);
}

public void btn_start_register_onclick(View view) {
Intent intent = new Intent(MainActivity.this,RegisterActivity.class);
startActivityForResult(intent,REQUEST_REGISTER_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(data == null){
return;
}
switch (requestCode){
case REQUEST_REGISTER_CODE:
tvstatus.setText("注册成功");
tvid.setText("ID:"+data.getStringExtra("id"));
tvemail.setText("Email:"+data.getStringExtra("email"));
break;
case REQUEST_SIGNIN_CODE:
tvstatus.setText("登录成功");
tvid.setText("您好,"+data.getStringExtra("id"));
tvemail.setText("");
break;
}

}
}

登陆界面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.example.timeemail;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class SigninActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signin);
}

public void btn_submit_signin_onclick(View view) {
EditText etId=findViewById(R.id.et_signin_id);
EditText etPassword=findViewById(R.id.et_signin_password);
Intent intent=new Intent();
intent.putExtra("id",etId.getText().toString());
intent.putExtra("password",etPassword.getText().toString());
setResult(0,intent);
finish();
}
}

注册界面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.example.timeemail;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class RegisterActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
}

public void btn_submit_register_onclick(View view) {
EditText etId=findViewById(R.id.et_reg_id);
EditText etEmail=findViewById(R.id.et_reg_email);
EditText etPassword=findViewById(R.id.et_reg_password);
Intent intent=new Intent();
intent.putExtra("id",etId.getText().toString());
intent.putExtra("email",etEmail.getText().toString());
intent.putExtra("password",etPassword.getText().toString());
setResult(0,intent);
finish();
}
}