我的安卓第一课:四大组件之一Activity及其组件RecyclerView

引言

讲述安卓中Activity的作用,安卓的一个Activity相当于一个页面,一个Activity由一个xml文件与java/kt文件组成。

XML

  • XML用于编写布局与样式(相当于HTML+CSS)
  • XML通常位于res/layout/**.xml

Java/Kt

  • Java/Kt用于编写逻辑(相当于JS)
  • Java/kt通常位于包名/**.java包名/**.kt

Activity 创建

1:创建 Java/Kotlin 类并继承 AppCompatActivity

scala 复制代码
package com.example.myapplication;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置当前 Activity 所使用的布局文件
        setContentView(R.layout.activity_main);
    }
}
  1. 创建对应的 XML 布局文件 res/layout/activity_main.xml
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是主页" />

    <Button
        android:id="@+id/btnNext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="跳转到下一页" />

</LinearLayout>

3:在 AndroidManifest.xml 中注册 Activity

xml 复制代码
<application
    android:allowBackup="true"
    android:label="My Applicaiton">

    <!-- 主 Activity -->
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" /> <!--标记为主界面-->
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

Activity 跳转

Activity 之间可以通过 Intent 实现跳转和通信。分为 显式 Intent 跳转隐式 Intent 跳转

显式跳转

主要用于本应用内的跳转。显式跳转需要手动指定调转到那个 Activity

  1. 当前上下文(Context),表示从哪个页面跳转出去
  2. 目标页面的类对象,告诉系统要跳转到哪个 Activity
java 复制代码
// 在 MainActivity.java 中
Button btnNext = findViewById(R.id.btnNext);
btnNext.setOnClickListener(v -> {
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    startActivity(intent);
});

隐式跳转

适用于调用系统应用或其他应用提供的功能,例如打开浏览器、拨打电话等。不直接指定目标组件,而是通过动作(Action)和数据(Data)让系统匹配合适的组件。依赖 <intent-filter> 来决定哪个应用或组件响应这个 Intent。需要同时匹配对应的 actioncategory

可能会弹出"选择器"让用户选择处理的应用。

比如

xml 复制代码
<activity android:name=".SecondActivity>
    <intent-filter>
        <action android:name="com.example.myapplication.ACTION"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

其中action与category中的内容,就是在Intent中需要填入的内容

java 复制代码
Intent intent = new Intent("com.example.myapplication.ACTION");
// 安卓可自动填入android.intent.category.DEFAULT
// intent.addCategory("android.intent.category.DEFAULT")

必须有可跳转的1到多个Activity

action与categoty内的内容可自定义

这个方式主要用于跳转系统应用,比如启动浏览器

java 复制代码
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("https://www.example.com")); 
startActivity(intent);

启动电话

java 复制代码
Intent intent = new Intent(Intent.ACTION_DIAL); 
intent.setData(Uri.parse("tel:10086")); startActivity(intent);
对比项 显式跳转 隐式跳转
是否指定目标组件 是(必须) 否(通过 Action/Data 匹配)
是否需要注册 intent-filter 是(目标组件需声明)
是否可能弹出选择器
应用场景 本应用内跳转 系统功能调用或跨应用通信
安全性 更安全 有一定风险(可能启动未知组件)

Activity相互传递数据

Activity 生命周期

  1. onCreate()。在每个Activity中都重写了这个方 法,它会在Activity第一次被创建的时候调用。在这个方法中完成Activity的初始化操作,比如加载布局、绑定事件等。
  2. onStart()。这个方法在Activity由不可见变为可见的时候调用
  3. onResume()。这个方法在Activity准备好和用户进行交互的时候调用。此时的Activity一 定位于返回栈的栈顶,并且处于运行状态。
  4. onPause()。这个方法在系统准备去启动或者恢复另一个Activity的时候调用 。通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶Activity的使用。
  5. onStop()。这个方法在Activity完全不可见的时候调用。它和onPause()方法的主要区别在于,如果启动的新Activity是一个对话框式的Activity,那么onPause()方法会得到执行,而onStop()方法并不会执行。
  6. onDestroy()。这个方法在Activity被销毁之前调用,之后Activity的状态将变为销毁状态。
  7. onRestart()。这个方法在Activity由停止状态变为运行状态之前调用,也就是Activity 被重新启动了。

TIP: onPause与onStop的相同点为,此时都启动了新的Activity。但区别是是否新的Activity是全屏的。

这些生命周期基本是两两相对的,比如 onCreate <--> onDestory, onStart <--> onStop, onResume <--> onStop以及onStart

savedInstanceState 与 onSaveInstanceState()

你是否疑惑,为什么onCreate带有参数savedInstanceState,这有什么用?

先关注下生命周期,从生命周期上来看我们发现了App process killed。对的,处于暂停状态的Activity有可能会被系统回收,再次进入就需要重新onCreate,如果我们的Activity是无状态的倒还好,但是如果其中存储了以下数据,此时就会导致数据丢失。所以安卓就提供了savedInstanceState,来让我们在Activity被回收前保存数据

java 复制代码
// Acitivty被回收前调用
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
}
  1. savedInstanceState 仅适用于临时性的 UI 状态数据,不适用于持久化存储
  2. savedInstanceState 不适合存储复杂的大对象

Activity 启动模式

安卓系统使用 的结构来管理Activity,设备页面上的Acitivity位于栈顶。运行中Activity(实例)也被称为一个Task。

standard

standard是Activity默认的启动模式,在不进行显式指定的情况下,所有Activity都会自动使用这种启动模式。

在standard模式下,

  1. 每当启动一个新的Activity,它就会在返回栈中入栈,并处于栈顶的位置。
  2. 系统不会在乎这个Activity是否已经在返回栈中存在,每次启动都会创建一个该 Activity的新实例。

singleTop

相对于standard重复创建新的实例,singleTop在启动Activity时

  1. 如果发现返回栈的栈顶已经是该Activity ,则认为可以直接使用它,不会再创建新的Activity实例
  2. 但当启动的Activity不在栈顶则依然会创建新实例。

singleTask

singleTop仅仅保证栈顶不重复,如果该Activity并没有处于栈顶的位置,还是可能会创建多个Activity实例。而当Activity的启动模式指定为singleTask时

  1. 每次启动该Activity时,系统首先会在返回栈中检查是否存在该Activity的实例,如果发现已经存在则直接使用该实例, 并把在这个Activity之上的所有其他Activity统统出栈
  2. 如果没有发现就会创建一个新的 Activity实例。

singleInstance

单例模式,指定为singleInstance模式的Activity会启用一个新的返回栈来管理这个Activity 。主要是为了解决各应用共享Activity 的问题。其他应用与本应用访问该Activity实例时,都会利用该新返回栈。

xml 复制代码
<activity android:name=".SecondActivity" 
    android:launchMode="singleInstance"> <!--!!!-->
        <intent-filter>
            <action android:name="com.example.activitytest.ACTION_START" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="com.example.activitytest.MY_CATEGORY" />
        </intent-filter>
</activity>

TIP:还需深度了解

Activity的UI:RecyclerView

在 Android 开发中,RecyclerView 是构建复杂、动态列表界面的核心组件之一 。它替代了早期的 ListView 和 GridView,提供了更高的灵活性和性能优化机制。RecyclerView 通常作为 Activity 中的一个重要 UI 组件来展示大量可滚动的数据集合。

RecyclerView 的核心机制依赖于两个关键类:RecyclerView.AdapterRecyclerView.ViewHolder

RecyclerView.Adapter

主要作用是将数据绑定到 UI 上,负责创建ViewHolder,并填充ViewHolder中的数据,可以说Adapter是数据与UI的桥梁,主要涉及到3个函数

当 RecyclerView 需要显示一个新的 item 时,如果没有可复用的 viewHolder,Adapter 就会通过 onCreateViewHolder() 方法来创建一个新的 ViewHolder。

ViewHolder 在构造时会加载并持有 item 的布局文件(如 item_layout.xml),从而为后续的数据绑定提供 UI 容器。

java 复制代码
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
                              .inflate(R.layout.item_layout, parent, false);
    return new MyViewHolder(view);
}

onBindViewHolder() 方法负责将指定位置的数据绑定到对应的 ViewHolder 上,即更新 UI 内容。

java 复制代码
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    ItemData item = dataList.get(position);
    holder.textView.setText(item.getTitle());
}

getItemCount() 方法告诉 RecyclerView 中有多少数据,从而决定创建多少个ViewHolder

java 复制代码
@Override
public int getItemCount() {
    return dataList.size();
}
  1. RecyclerView 需要显示视图的时候,首先找Adapter,调用它的getItemCount()函数,询问数组列表中一共有多少个对象需要显示。
  2. 随后继续调用onCreateViewHolder()函数,创建相应的ViewHolder对象和ViewHolder需要显示的view
  3. 接着调用onBindViewHolder(),得到对应的ViewHolder和位置,将数据绑定到ViewHolder视图上,也就是去修改具体的控件。

RecyclerView.ViewHolder

负责容纳View视图(具体控件)。也就是RecyclerView中填充的视图是由ViewHolder提供的。在创建ViewHolder时会传入相应的布局,然后通过布局去配置具体的控件

java 复制代码
public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView textView;
    public ImageView imageView;

    public MyViewHolder(View layout) {
        super(itemView);
        textView = layout.findViewById(R.id.text_view);
        imageView = layout.findViewById(R.id.image_view);
    }
}

一个 Adapter 持有多个 ViewHolder,每个 ViewHolder 又持有多个控件

组件 数量 描述
Adapter 1 个 控制整个列表的数据和展示逻辑,协调多个 ViewHolder
ViewHolder 多个(根据可见 item 数量动态创建) 每个 ViewHolder 对应一个 item 布局实例
View / 控件 每个 ViewHolder 中持有多个 如 TextView、ImageView 等 UI 控件
相关推荐
婵鸣空啼3 小时前
GD图像处理与SESSiON
android
sunly_3 小时前
Flutter:导航固定背景图,滚动时导航颜色渐变
android·javascript·flutter
用户2018792831674 小时前
简单了解android.permission.MEDIA_CONTENT_CONTROL权限
android
_一条咸鱼_4 小时前
Android Runtime类卸载条件与资源回收策略(29)
android·面试·android jetpack
顾林海4 小时前
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
android·面试·性能优化
砖厂小工4 小时前
Now In Android 精讲 8 - Gradle build-logic 现代构建逻辑组织方式
android
玲小珑4 小时前
Auto.js 入门指南(八)高级控件与 UI 自动化
android·前端
harry235day4 小时前
Compose 带动画的待办清单列表页
android·android jetpack
咕噜企业签名分发-淼淼5 小时前
如何实现安卓端与苹果端互通的多种方案
android