Android——「Activity、Intent、Context」

前言

学习 Activity、Intent、Context

@toc

一、Activity

  • 组件的概念
    • Android中的主要组件包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider

1、继承关系

java 复制代码
java.lang.Object
   ↳	android.content.Context
 	   ↳	android.content.ContextWrapper
 	 	   ↳	android.view.ContextThemeWrapper
 	 	 	   ↳	android.app.Activity
  • 通过这种继承,Activity就集成了Context的能力,可以访问资源、数据库、SharedPreferences等,同时作为Context的子类,Activity也可以作为Context参数被传递使用。
  • 这种继承关系让Activity既是一个 UI 组件,也是一个Context,很好地结合了两者的功能。

2、简介

  • Activity 代表应用程序的单个屏幕,用户可以使用该屏幕执行单一、集中的任务,Activity 通常以全屏窗口的形式呈现给用户;
  • Activity 是一个应用程序组件,单个用户任务的单个屏幕;
  • 每个 Activity 都有自己的布局文件;
  • 可以为 Activity 分配父子关系,以在应用程序中启用向上导航;
  • 一个应用程序通常由多个彼此松散的屏幕组成。每个屏幕都是一个 Activity;
  • 应用程序中有一个主Activity(MainActivity.java),在应用程序启动时呈现给用户;通过主Activity 可以启动其他 Activity 来执行不同的操作;
  • 每次启动新活动,前一个 Activity 都会停止,但系统会将该 Activity 保留在堆栈中;当新 Activity 启动时,该新 Activity 被推入后台堆栈并获取用户焦点;当用户完成当前 Activity 并按下后退按钮时,该 Activity 将从堆栈中弹出并销毁,并恢复上一个 Activity;
  • Intent 是一条异步消息,可以在 Activity 中使用它来请求来自另一个 Activity 或某个其他应用程序组件的操作;可以使用 Intent 从一个 Activity 启动另一个 Activity,并在 Activity 之前传递数据;

二、Intent

1、简介

  • 允许从应用程序中的另一个组件请求操作。例如,从另一个组件启动一个 Activity;
  • 显示 Intent:可以指示接收数据的特定目标组件;
  • Intent 附加信息是 Bundle,键值对;

2、知识点

  • 是什么
    • Intent 是一种用于在应用程序的不同组件之间进行通信的机制;
  • 作用
    • 允许应用程序中的一个组件向另一个组件发送请求,以便执行某种操作或进行交换;
    • 通过使用 Intent,不同组件可以进行解耦,实现模块化和灵活的交互;
  • 用途
    • 启动 Activity:通过指定目标 Activity 的类名或其它标识,可以告诉系统启动相应的 Activity,并传递数据或参数;
    • 启动服务 Service:以用于启动服务,以在后台执行某些任务或处理长时间运行的操作;
    • 发送广播 Broadcast
      • 通过发送 Intent 广播,可以通知其他组件或应用程序发生了某个事件,以便它们采取相应的操作;
    • 传递数据
      • Intent 可以承载数据,可以通过 extra 数据来传递附加信息给目标组件。数据可以为基本数据类型也可以为对象类型;

3、实现

1)两个页面之间传递数据

  • 场景:将一个 Activity 的数据传送给另一个 Activity;
    • 实现思路 :将要传递的数据挂到 Intent 里面,通过 Intent 将数据进行传递;
    • 实现方式
      • 分散传递

        java 复制代码
        Intent intent = new Intent(this, Activity2.class);  //' 当前的页面传到Activity2
        // 可以分别传递多条不同类型的数据
        Intent.putExtra("userName", "Yjx");  // 键值对
        Intent.putExtra("age", 18);
        Intent.putExtra("isLogin", false);
        startActivity(intent);
      • 打包传递------Bundle

        • Bundle 类来打包数据来进行传递;
        • 打多个包传递------给 Bundle 起个名字;
      • 传递对象类型的数据

        • 场景:传递一个自定义的对象(JavaBean),将数据和函数封装成一个对象,一下子全部传递过去;

        • 传递过程中,对象与基本类型数据的区别,就是多了 序列化;

        • 序列化:可以简单理解为使得对象在数据流中方便地进行传递;即将对象可以变成可以传递的数据,反序列化就是传递过去之后可以将对象解析出来;

        • 对象序列化的方式(强制类型转换为 Serializable 和 Parcelable)

          java 复制代码
          // 传递对象(在 Activity A)
          // 写在控件监听事件中
          Intent intent = new Intent(this, Activity.class);
          User user = new User();
          intent.putExtra("user", (Serializable) user);
          startActivity(intent);
          java 复制代码
          // 接收对象(在 Activity B)
          // 写在 onCreate() 函数中
          Intent intent = getIntent();
          if (intent != null) {
          	User user = (User) intent.getSerializableExtra("user");
          }

2)回传数据

  • 应用场景:修改完个人信息回退到上一个页面;
  • 一个 Activity 跳转到 Activity1,并希望从 Activity1 回到Activity的时候,收到 Activity1 带回来的数据;

4、显示跳转和隐式跳转

  • 应用场景
    • 显示跳转:跳转当前应用 app 内的页面用显示跳转方式即可;
    • 隐式跳转:主要用于往其它应用 app 的页面进行跳转;
  • 隐式的理解
    • 如何从一个页面跳转到另一个页面;
    • 不需要明确的指明要跳转到哪个页面,而是通过条件筛选确定目的页面;
  • 隐式跳转的流程
    • 目的:从一个源 Activity 跳转到目标 Activity;
    • 通过 intent 设置条件
      • 显示启动
        • 通过设置好源和目的地,明确地告诉它从某个地方跳转到某个地方;
      • 隐式启动
        • Intent 设置条件;
        • 系统会遍历 Manifest 文件,查询找到符合条件的 Activity
          • 查询:通过 Activity 标签下的 (过滤器)筛选符合条件的 Activity;
          • 如果匹配(符合条件),就可以认为 Intent 打开这个 目标 Activity ;
          • 如果符合条件的有多个 Activity,系统就会将符合条件的给你列出来,让用户去选择;

5、步骤

  • 1)在 Intent 代码中设置条件
  • 2)在 Mainfest 条件中设置过滤条件 想要此 Acitivty 被其它页面跳转过来时才需要写过滤条件(一种是自定义的条件:用来跳转到自己写的页面;一种是系统提供的条件:用来跳转到系统其他 app 的页面(常用))

三、Context

  • 是什么:可以理解为:"从哪里来";告诉我们当前代码是从哪里来的,是隶属于谁的;
java 复制代码
class MainActivity extends AppCompatActivity {
    
    btnToastShort.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 这个this的类型是context,表明:因为 Toast 是在 MainActivity 这个类中
        // context 传入this,表明当前产生 Toast 是MainActivity我让你做的,是从我这里来的
    	Toast.makeText(MainActivity.this, "你点击了", Toast.LENGTH_SHORT).show();  
    }
});
}
  • 因为 onClick 方法被匿名内部类包裹着,处于匿名内部类中,则这里的 this 表示的当前匿名内部类的对象;这里不能用 this,这里的 this 表示的是匿名内部类的对象

  • 作用:用来访问全局信息(应用程序的资源,图片资源、字符串资源),一些常用的组件(Activity、Service)继承自 Context(继承后具有访问全局资源的能力),目的是通过 Context 方便地访问资源;

  • setText 的实现:getContext():获取相关的 Context 对象,getResource():获取资源管理器,getText(id):返回资源 id 的字符串;

    java 复制代码
    // 访问字符串资源
    public class MainActivity extends AppCompatActivity {
        private TextView tv;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            tv = new TextView(this);  // this:MainActivity的实例,将this传给context,在内部对context有一个引用
            tv.setText(R.string.hello_world); 
            setContentView(tv);  // 指定一个视图
            }
    }
    java 复制代码
    // 访问图片资源
    public class MainActivity extends AppCompatActivity {
      
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
           	ImageView iv = new ImageView(this);
           	iv.setImageResource(R.mipmap.ic_launcher);
            }
    }

四、实践 Lab

1、需求

  • 创建并构建两个 Activity(Activity1 和 Activity2);
  • Activity1 作为主 Activity,主要包含一个 "发送" 按钮,当用户点击此按钮将使用 Intent 来启动 Activity2;
  • 主 Activity 中添加 EditText,用户输入消息,并点击发送按钮,主 Activity 使用 Intent 来启动第二个 Activity 并将用户的消息发送到第二个 Activity,第二个 Activity 显示它接收到的消息
  • 第二个 Activity 添加 EditText 和回复按钮;用户键入回复消息并点击回复按钮,使用 Intent 将回复消息从第二个 Activity 传递给主 Activity,并显示;

2、代码实现

  • 创建第一个Activity 布局
java 复制代码
// activity_main.xml(主Activity)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="16dp"
        android:textColor="@android:color/background_dark"
        android:layout_marginBottom="16dp"
        android:onClick="launchSecondActivity"
        android:text="@string/button_main" />

    <EditText
        android:id="@+id/editText_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_marginStart="32dp"
        android:layout_marginLeft="32dp"
        android:layout_marginBottom="19dp"
        android:ems="10"
        android:inputType="text"
        android:text="Name" />
</RelativeLayout>
  • 创建第二个Activity 布局
java 复制代码
// 第二个Activity
<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"
    tools:context=".SecondActivity">

    <TextView
        android:id="@+id/text_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/text_header"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="60dp"
        android:layout_marginTop="40dp"
        android:text=""
        android:textAppearance="AppCompat.Medium"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_header" />
</androidx.constraintlayout.widget.ConstraintLayout>
  • 主 Activity 添加 Intent
java 复制代码
   public void launchSecondActivity(View view) {
        // 将显示Intent添加到主Activity,Intent用于单击发送按钮时激活第二个Activity
        // 参数:第一个参数,应用程序Context;第二个参数:将接收该Intent的特定组件
        // 当点击发送按钮时,MainActivity发送Intent并启动第二个Activity 出现在屏幕
        Intent intent = new Intent(this, SecondActivity.class);
        startActivity(intent);
    }
}
  • 从主 Activity 发送数据到第二个 Activity
    • 使用 Intent 将数据从一个 Activity 发送到另一个 Activity
    • Intent 传递数据到目标 Activity 的方式
      • 1)数据字段:Intent 数据指要操作的特定数据的 URl
      • 2)Intent 附加信息,如果传递的数据不是 URl 或想要发送多条信息,可以将附加信息放入 extras 中。
      • Intent 附加信息内容是 Bundle 。Bundle 是数据集合,存储形式为键值对;
      • 从一个 Activity 传递信息到另一个 Activity,可以将键和值放入发送 Activity 的 Intent extra 中,然后在接收 Activity 中将它们取出;

Bundle 中包含其他数据,本需求中为用户输入的字符串

java 复制代码
public class MainActivity extends AppCompatActivity {
    private static final String LOG_TAG = MainActivity.class.getSimpleName();
    public static final String EXTRA_MESSAGE = "com.example.myapplication.extra.MESSAGE";
    private EditText mMessageEditText;
    public static final int TEXT_REQUEST = 1;  // 第二个Activity回复响应的键
    private TextView mReplyHeadTextView;  // 回复标头Textview
    private TextView mReplyTextView;  // 回复TextView元素


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);  // 指定一个视图
        mMessageEditText = findViewById(R.id.editText_main);  // 使用findViewById()获取对 EditText 的引用
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
        }


    public void launchSecondActivity(View view) {
        // 将显示Intent添加到主Activity,Intent用于单击发送按钮时激活第二个Activity
        // 参数1:应用程序Context和将接收该Intent的特定组件
        // 当点击发送按钮时,MainActivity发送Intent并启动第二个Activity 出现在屏幕
        Intent intent = new Intent(this, SecondActivity.class);
        String message = mMessageEditText.getText().toString();
        intent.putExtra(EXTRA_MESSAGE, message);
        startActivityForResult(intent, TEXT_REQUEST);

    }

    @Override
    // 回调方法
    // requestCode:请求
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // 处理返回数据
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == TEXT_REQUEST) {
            if (requestCode == RESULT_OK) {
                String reply =
                        data.getStringExtra(SecondActivity.EXTRA_REPLY);
                mReplyHeadTextView.setVisibility(View.VISIBLE);
                mReplyTextView.setText(reply);
                mReplyTextView.setVisibility(View.VISIBLE);
            }
        }
    }
}
  • 将数据从第二个 Activity 返回给主 Activity startActivity():使用显式 Intent 启动另一个 Activity 时,不会期望返回任何数据,只是激活该 Activity; 如果想从激活的 Activity 中获取数据,则需要以 startActivityForResult() 启动它
java 复制代码
public class SecondActivity extends AppCompatActivity {
    public static final String EXTRA_REPLY = "com.example.myapplication.extra.REPLY";
    private EditText mReply;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        mReply = findViewById(R.id.editText_second);
        // 获取激活此Activit的Intent
        Intent intent = getIntent();
        // 获取Intent extra中包含的字符串
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
        // 获取要显示的控件的引用
        TextView textView = findViewById(R.id.text_message);
        // 通过引用在此控件上显示获取Intent extra中包含的字符串
        textView.setText(message);
    }

    public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        finish();
    }
}
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui