【Android Jetpack】Lifecycle 感知生命周期

文章目录

    • 背景
    • 示例
    • LifeCycle的原理
      • LifecycleOwner
      • 自定义LifecycleOwner
      • LifecycleObserver
    • 示例改进
    • 使用LifecycleService解耦Service与组件
    • 整个应用进程的生命周期ProcessLifecycleOwner

背景

在Android应用程序开发中,解耦很大程度上表现为系统组件的生命周期与普通组件之间的解耦。普通组件在使用过程中通常需要依赖于系统组件的生命周期。有时候,我们不得不在系统组件的生命周期回调方法中,主动对普通组件进行调用或控制。因为普通组件无法主动获知系统组件的生命周期事件。

我们希望我们对自定义组件的管理,不依赖于页面生命周期的回调方法。同时,在页面生命周期发生变化时,也能够及时收到通知。这在组件化和架构设计中显得尤为重要。

为此,Google提供了LifeCycle作为解决方案。LifeCycle可以帮助开发者创建可感知生命周期的组件。这样,组件便能够在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏发生的可能性。LifeCycle不只对Activity/Fragment有用,在Service和Application中也能大显身手。

示例

Android开发中,经常需要管理生命周期。举个栗子,我们需要获取用户的地址位置,当这个Activity在显示的时候,我们开启定位功能,然后实时获取到定位信息,当页面被销毁的时候,需要关闭定位功能。

internal class MyLocationListener(
        private val context: Context,
        private val callback: (Location) -> Unit
) {

    fun start() {
        // 连接系统定位服务以及其他业务
    }

    fun stop() {
        //断开系统定位服务
    }
}

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this) { location ->
            ...
        }
    }

    public override fun onStart() {
        super.onStart()
        myLocationListener.start()
    }

    public override fun onStop() {
        super.onStop()
        myLocationListener.stop()
    }
}

虽然此示例看起来没问题,但在真实的应用中,最终会有太多管理界面和其他组件的调用,以响应生命周期的当前状态。管理多个组件会在生命周期方法(如 onStart()onStop())中放置大量的代码,这使得它们难以维护。

此外,无法保证组件会在 Activity 或 Fragment 停止之前启动。在我们需要执行长时间运行的操作(如 onStart() 中的某种配置检查)时尤其如此。这可能会导致出现一种竞态条件,在这种条件下,onStop() 方法会在 onStart() 之前结束,这使得组件留存的时间比所需的时间要长。

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this) { location ->
            // update UI
        }
    }

    public override fun onStart() {
        super.onStart()
        Util.checkUserStatus { result ->
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start()
            }
        }
    }

    public override fun onStop() {
        super.onStop()
        myLocationListener.stop()
    }

}

Lifecycle类是一个持有组件(activityfragment)生命周期信息的类,其他对象可以观察该状态。Lifecycle使用两个重要的枚举部分来管理对应组件的生命周期的状态:

  • Event:生命周期事件,由系统来分发,这些事件对应于ActivityFragment的生命周期函数。

  • State:Lifecycle对象所追踪的组件的当前状态

image-20230921165716822

LifeCycle的原理

Jetpack为我们提供了两个类:

  • LifecycleOwner: 被观察者
  • LifecycleObserver: 观察者

通过观察者模式,实现对页面生命周期的监听。

public class AppCompatActivity extends FragmentActivity implements AppCompatCallback,
        TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {
}            
public class FragmentActivity extends ComponentActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback,
        ActivityCompat.RequestPermissionsRequestCodeValidator {
}            

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }            
}           
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, SavedStateRegistryOwner {
}            

ComponentActivity和Fragment已经默认实现了LifecycleOwner接口。(代表有生命周期)

LifecycleOwner

那什么是LifecycleOwner呢?实现LifecycleOwner接口就表示这是个有生命周期的类他有一个getLifecycle()方法是必须实现的。

 //一个具有Android生命周期的类。自定义组件可以使用这些事件来处理生命周期更改,而无需在Activity或Fragment中实现任何代码。
@SuppressWarnings({"WeakerAccess", "unused"})
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

从以上源码可知,Activity和Fragment已经替我们实现了被观察者应该实现的那一部分代码。因此,我们不需要再去实现这部分代码。当我们希望监听Activity的生命周期时,只需要实现观察者那一部分的代码,即让自定义组件实现LifecycleObserver接口即可。该接口没有接口方法,无须任何具体实现。

对于前面提到的监听位置的例子。可以把MyLocationListener实现LifecycleObserver,然后在Lifecycle(Activity/Fragment)onCreate方法中初始化。这样MyLocationListener就能自行处理生命周期带来的问题。

自定义LifecycleOwner

  • 如果想在自定义的类中实现LifecyclerOwner,就需要用到LifecycleRegistry类,并且需要自行发送Event:
class MyActivity : Activity(), LifecycleOwner {
    private lateinit var lifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleRegistry = LifecycleRegistry(this)
        lifecycleRegistry.markState(Lifecycle.State.CREATED)
    }

    public override fun onStart() {
        super.onStart()
        lifecycleRegistry.markState(Lifecycle.State.STARTED)
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

LifecycleObserver

/**
 * Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on
 * {@link OnLifecycleEvent} annotated methods.
 * @see Lifecycle Lifecycle - for samples and usage patterns.
 //-------------
 * 将类标记为LifecycleObserver。它没有任何方法,而是依赖于
 *{@link OnLifecycleEvent}注释的方法。
 *@请参阅生命周期-了解示例和使用模式。
 */
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {

}

注释上写的很明白,该接口依赖OnLifecycleEvent的注解方法

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnLifecycleEvent {
    Lifecycle.Event value();
}
public enum Event {
    /**
         * Constant for onCreate event of the {@link LifecycleOwner}.
         */
    ON_CREATE,
    /**
         * Constant for onStart event of the {@link LifecycleOwner}.
         */
    ON_START,
    /**
         * Constant for onResume event of the {@link LifecycleOwner}.
         */
    ON_RESUME,
    /**
         * Constant for onPause event of the {@link LifecycleOwner}.
         */
    ON_PAUSE,
    /**
         * Constant for onStop event of the {@link LifecycleOwner}.
         */
    ON_STOP,
    /**
         * Constant for onDestroy event of the {@link LifecycleOwner}.
         */
    ON_DESTROY,
    /**
         * An {@link Event Event} constant that can be used to match all events.
         */
    ON_ANY
}

示例改进

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // lifecycle是LifecycleOwner接口的getLifecycle()方法得到的
        lifecycle.addObserver(MyObserver()) 
    }
}

在Activity中只需要引用MyObserver即可,不用再关心Activity生命周期变化对该组件所带来的影响。生命周期的管理完全交给MyObserver内部自行处理。在Activity中要做的只是通过getLifecycle().addObserver()方法,将观察者与被观察者绑定起来。

class MyObserver : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun connectListener() {
        ...
        //填写逻辑业务代码
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun disconnectListener() {
        ...
        //填写逻辑业务代码
    }
}

上面的lifecycle.addObserver(MyObserver()) 的完整写法应该是aLifecycleOwner.getLifecycle().addObserver(new MyObserver())aLifecycleOwner一般是实现了LifecycleOwner的类,比如Activity/Fragment

internal class MyLocationListener(
        private val context: Context,
        private val lifecycle: Lifecycle,
        private val callback: (Location) -> Unit): LifecycleObserver {

    private var enabled = false

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start() {
        if (enabled) {
            // connect
        }
    }

    fun enable() {
        enabled = true
        // 查询状态
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop() {
        // disconnect if connected
    }
}
  • 对于组件中那些需要在页面生命周期发生变化时得到通知的方法,我们需要在这些方法上使用==@OnLifecycleEvent(Lifecycle.Event.ON_XXX)==标签进行标识。这样,当页面生命周期发生变化时,这些被标识过的方法便会被自动调用。

LifeCycle完美解决了组件对页面生命周期的依赖问题,使组件能够自己管理其生命周期,而无须在页面中对其进行管理。这无疑大大降低了代码的耦合度,提高了组件的复用程度,也杜绝了由于对页面生命周期管理的疏忽而引发的内存泄漏问题,这在项目工程量大的情况下是非常有帮助的。

使用LifecycleService解耦Service与组件

拥有生命周期概念的组件除了Activity和Fragment,还有一个非常重要的组件是Service。为了便于对Service生命周期的监听,达到解耦Service与组件的目的,Android提供了一个名为LifecycleService的类。该类继承自Service,并实现了LifecycleOwner接口。与Activity/Fragment类似,它也提供了一个名为getLifecycle()的方法供我们使用。

  • 想要使用LifecycleService必须先增加lifecycle-service的依赖:
implementation 'androidx.lifecycle:lifecycle-service:2.3.1'

结构:

public class LifecycleService
    extends Service implements LifecycleOwner
java.lang.Objectandroid.content.Contextandroid.content.ContextWrapperandroid.app.Serviceandroidx.lifecycle.LifecycleService 

源码:

public class LifecycleService extends Service implements LifecycleOwner {

    private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);

    @CallSuper
    @Override
    public void onCreate() {
        mDispatcher.onServicePreSuperOnCreate();
        super.onCreate();
    }

    @CallSuper
    @Nullable
    @Override
    public IBinder onBind(@NonNull Intent intent) {
        mDispatcher.onServicePreSuperOnBind();
        return null;
    }

    @SuppressWarnings("deprecation")
    @CallSuper
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        mDispatcher.onServicePreSuperOnStart();
        super.onStart(intent, startId);
    }

    // this method is added only to annotate it with @CallSuper.
    // In usual service super.onStartCommand is no-op, but in LifecycleService
    // it results in mDispatcher.onServicePreSuperOnStart() call, because
    // super.onStartCommand calls onStart().
    @CallSuper
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @CallSuper
    @Override
    public void onDestroy() {
        mDispatcher.onServicePreSuperOnDestroy();
        super.onDestroy();
    }

    @Override
    @NonNull
    public Lifecycle getLifecycle() {
        return mDispatcher.getLifecycle();
    }
}

整个应用进程的生命周期ProcessLifecycleOwner

具有生命周期的系统组件除Activity、Fragment、Service外,还有Application。很多时候,我们会遇到这样的需求:我们想知道应用程序当前处在前台还是后台,或者当应用程序从后台回到前台时,我们能够得到通知。有不少方案能够实现该需求,但都不够好。在此之前,Google并没有为该需求提供官方解决方案,直到LifeCycle的出现。

  • 需要先添lifecycle-process的依赖:
implementation 'androidx.lifecycle:lifecycle-process:2.3.1'

源码:

/**
 * Class that provides lifecycle for the whole application process.
 * <p>
 * You can consider this LifecycleOwner as the composite of all of your Activities, except that
 * {@link Lifecycle.Event#ON_CREATE} will be dispatched once and {@link Lifecycle.Event#ON_DESTROY}
 * will never be dispatched. Other lifecycle events will be dispatched with following rules:
 * ProcessLifecycleOwner will dispatch {@link Lifecycle.Event#ON_START},
 * {@link Lifecycle.Event#ON_RESUME} events, as a first activity moves through these events.
 * {@link Lifecycle.Event#ON_PAUSE}, {@link Lifecycle.Event#ON_STOP}, events will be dispatched with
 * a <b>delay</b> after a last activity
 * passed through them. This delay is long enough to guarantee that ProcessLifecycleOwner
 * won't send any events if activities are destroyed and recreated due to a
 * configuration change.
 *
 * <p>
 * It is useful for use cases where you would like to react on your app coming to the foreground or
 * going to the background and you don't need a milliseconds accuracy in receiving lifecycle
 * events.
 */
/**
翻译:
*为整个应用程序流程提供生命周期的类。
*您可以将此LifecycleOwner视为所有活动的组合,除了
*{@link Lifecycle。事件#ON_CREATE}将被调度一次,并且{@linkLifecycle。事件#ON_DESTROY}
*永远不会被派遣。其他生命周期事件将按照以下规则进行调度:
*ProcessLifecycleOwner将调度{@link Lifecycle。事件#ON_START},
*{@linkLifecycle.Event#ON_RESUME}事件,作为第一个活动在这些事件中移动。
*{@link Lifecycle。Event#ON_PAUSE},{@link Lifecycle。Event#ON_STOP},事件将与上次活动后的a延迟穿过他们。此延迟足够长,可以保证ProcessLifecycleOwner
*如果活动由于配置更改。
*它适用于您希望对应用程序进入前台或
*进入后台,在接收生命周期中不需要毫秒的准确性事件。
*/
@SuppressWarnings("WeakerAccess")
public class ProcessLifecycleOwner implements LifecycleOwner {

ProcessLifecycleOwner的使用方式与Activity、Fragment和Service是类似的,其本质也是观察者模式。由于我们要观察的是整个应用程序,因此,需要在Application中进行相关代码的编写。

class StApplication : Application() {
    companion object {
        private lateinit var instance: Application
        fun getInstance() = instance
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
        ProcessLifecycleOwner.get().lifecycle.addObserver(MyApplicationObserver())
    }
}
class MyApplicationObserver : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {

    }
    // 前台出现时调用
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        Log.e("xoliu", "onStart")
    }
    // 前台出现时调用
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume() {
        Log.e("xoliu", "onResume")
    }
    // 退出到后台时调用
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        Log.e("xoliu", "onPause")
    }
    // 退出到后台时调用
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        Log.e("xoliu", "onStop")
    }
}
  • 当应用程序从后台回到前台,或者应用程序被首次打开时,会依次调用Lifecycle.Event.ON_STARTLifecycle.Event.ON_RESUME

  • 当应用程序从前台退到后台(用户按下Home键或任务菜单键),会依次调用Lifecycle.Event.ON_PAUSELifecycle.Event.ON_STOP。需要注意的是,这两个方法的调用会有一定的延后。这是因为系统需要为“屏幕旋转,由于配置发生变化而导致Activity重新创建”的情况预留一些时间。也就是说,系统需要保证当设备出现这种情况时,这两个事件不会被调用。因为当旋转屏幕时,你的应用程序并没有退到后台,它只是进入了横/竖屏模式而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/203964.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux学习笔记09、Shell命令之历史命令和自动补全

上一篇&#xff1a;Linux学习笔记08、Shell命令之常用命令缩写及全称 目录 1、历史命令&#xff1a; 1.1、查看所有历史命令列表&#xff1a; 1.2、查看指定历史命令&#xff1a; 1.3、清除历史命令&#xff1a; 2、自动补全 2.1、当字符串唯一时&#xff1a; 2.2、当有多个…

在编程中遇到的问题总结

IDEA空包粘黏问题 创建好目录以后会发现idea自动将空包合并在一起了&#xff0c;而且点击设置里面也没有Compact Middle Package Compact Middle Package如果不在设置的主面板上&#xff0c;则点击Tree Appearance&#xff0c;会发现Compact Middle Package在Tree Appearance里…

【JavaEE初阶】volatile 关键字、wait 和 notify

目录 一、volatile 关键字 1、volatile 能保证内存可见性 2、volatile 不保证原子性 二、wait 和 notify 1、wait()方法 2、notify()方法 3、notifyAll()方法 4、wait 和 sleep 的对比 一、volatile 关键字 1、volatile 能保证内存可见性 我们前面的线程安全文章中&…

【物联网与大数据应用】Hadoop数据处理

Hadoop是目前最成熟的大数据处理技术。Hadoop利用分而治之的思想为大数据提供了一整套解决方案&#xff0c;如分布式文件系统HDFS、分布式计算框架MapReduce、NoSQL数据库HBase、数据仓库工具Hive等。 Hadoop的两个核心解决了数据存储问题&#xff08;HDFS分布式文件系统&#…

国产CPU计算平台选型指南

信创&#xff0c;这两年已经不是什么新鲜词了&#xff0c;随着29号文、79号文的实施落地&#xff0c;信创产品加速从党政走向八大关基行业。 八大行业中&#xff0c;金融、教育、电信、石油等企业步伐更大&#xff0c;很多企业已经从窗口业务、日常办公这类轻量应用场景&#…

什么是灯塔工厂?灯塔工厂的作用?

什么是灯塔工厂&#xff1f; "灯塔工厂"概念源于德国的工业4.0战略&#xff0c;又称“工业4.0示范工厂”或“标杆工厂”&#xff0c;代表工业领域顶级的智能制造能力。2018年&#xff0c;由世界经济论坛和麦肯锡共同推出。 灯塔工厂是通过数字化、网络化和智能化手…

LeetCode(43)快乐数【哈希表】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 快乐数 1.题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也…

pygame图像变换:缩放、旋转、镜像

文章目录 函数列表图像显示翻转缩放旋转 函数列表 pygame的transform中封装了一些基础的图像处理函数&#xff0c;列表如下 函数功能flip镜像scale缩放至新的分辨率scale_by根据因子进行缩放scale2x专业图像倍增器rotate旋转rotozoom缩放并旋转smoothscale平滑缩放smoothscal…

山西电力市场日前价格预测【2023-12-01】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-12-01&#xff09;山西电力市场全天平均日前电价为246.08元/MWh。其中&#xff0c;最高日前电价为402.66元/MWh&#xff0c;预计出现在17:45。最低日前电价为0.00元/MWh&#xff0c;预计出…

[cocos creator]EditBox,editing-return事件,清空输入框

需求&#xff1a; 监听EditBox&#xff0c;editing-return 回车事件&#xff0c;在输入框内点击回车后&#xff0c;发送内容&#xff0c;并清空输入框 问题&#xff1a; 设置node.getComponent(EditBox).string ; 没有效果 解决办法&#xff1a; //设置string 为空 this.v…

直击广州车展 | 远航汽车“卷”出新高度

第23届广州车展作为2023年汽车行业的年度收官之作&#xff0c;成为各大汽车厂商“秀肌肉”的绝佳舞台&#xff0c;22万平方米的开放展区内容纳了1132辆展车&#xff0c;包括全球首发车59辆、概念车20辆、新能源车469辆。 新能源汽车产业发展迅猛&#xff0c;得益于新能源车型在…

如何使用Windows自带的IIS服务搭建本地站点并远程访问

文章目录 1.前言2.Windows网页设置2.1 Windows IIS功能设置2.2 IIS网页访问测试 3. Cpolar内网穿透3.1 下载安装Cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5.结语 1.前言 在网上各种教程和介绍中&#xff0c;搭建网页都会借助各种软件的帮助&#xf…

去北京医院预约,需要医保卡号,但是社保卡不在身边,北京的医保卡号咋网上查询

目录 1 问题2 查询 1 问题 要去北京某一个医院预约挂号&#xff0c;预约的时候选择的医保&#xff0c;需要写医保卡号&#xff0c;但是自己的社保卡不在身边&#xff0c;怎么办 记住&#xff0c;医保卡号不是社保卡号&#xff0c;是不一样的 北京医保卡号是12位 2 查询 登陆这…

Adobe InCopy の Adobe InDesign 大联动

今天我们再来进行Adobe全家桶剩余几位的介绍~ Adobe InCopy是一款专业的文字编辑和校对软件&#xff0c;它是InDesign的附属软件&#xff0c;主要用于编辑、校对和协作文本内容。InCopy提供了一系列功能&#xff0c;使得编辑和校对文本变得更加简单和高效。在InCopy中&#xff…

MongoDB快速入门及其SpringBoot实战

MongoDB快速入门及其SpringBoot实战 MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计就是用于简化开发和方便扩展&am…

配电室智慧运维监控系统

配电室智能运维监控系统是一个综合性的管理系统&#xff0c;专门针对配电室的运维工作进行设计。依托电易云-智慧电力物联网&#xff0c;它融合了先进的监测技术、自动化技术、数据分析技术等&#xff0c;对配电室进行全方位、实时的智能化监控和管理&#xff0c;以提升配电室运…

【C++】赋值运算符重载

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

解决noauth authentication required异常

今天在使用redis数据库的时候&#xff0c;突然给报了个这个错误&#xff0c;上网一查才知道是因为 Redis 服务器需要密码进行身份验证&#xff0c;因此&#xff0c;我们需要通过auth password 进行身份验证。不过我这个密码还是试了很多次才想起来的&#xff0c;哦好像是听网课…

2023.11.29 关于 MyBatis resultMap 和 多表查询

目录 resultType 和 resultMap 多表查询 resultType 和 resultMap 在 MyBatis 中二者被用于设置查询后所返回的数据类型 resultType 大多数情况下均可使用 resultType 进行设置返回数据类型 实例理解 下图为数据库中的一个 user 表&#xff0c;该 user 表包含四个字段 为了能…