119.Android 简单的软键盘和菜单无缝切换效果,聊天界面软键盘无缝切换

news2024/12/23 12:40:04

//此效果主要通过动态设置windowSoftInputMode三种状态的切换实现:SOFT_INPUT_ADJUST_NOTHING、SOFT_INPUT_ADJUST_PAN、SOFT_INPUT_ADJUST_RESIZE。

 

1.第一步 导入需要用到的依赖库:

//RecyclerView
implementation 'com.android.support:recyclerview-v7:28.0.0'

//RecyclerAdapter
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28'

2.第二步 新建SeamlessSwitchActivity页面,注意manifest里设置windowSoftInputMode为stateHidden|adjustResize:

//manifest: 

<activity
    android:name=".phone.activity.SeamlessSwitchActivity"
    android:launchMode="singleTop"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden|adjustResize"
    tools:ignore="LockedOrientationActivity" />

//activity:

/**
 * @author CJF
 */
public class SeamlessSwitchActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {
    private final LinearLayoutManager manager = new LinearLayoutManager(this);
    private final SdkAdapter adapter = new SdkAdapter(R.layout.sdk_item);
    private SystemKeyboardUtils systemKeyboardUtils;
    private View mSeamlessSwitchBottomLayout;
    private RecyclerView mSeamlessSwitchRecy;
    private ImageView mSeamlessSwitchMore;

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

        mSeamlessSwitchMore = findViewById(R.id.mSeamlessSwitchMore);
        mSeamlessSwitchBottomLayout = findViewById(R.id.mSeamlessSwitchBottomLayout);
        mSeamlessSwitchRecy = findViewById(R.id.mSeamlessSwitchRecy);
        mSeamlessSwitchMore.setOnClickListener(this);
        mSeamlessSwitchRecy.setOnTouchListener(this);

        //软键盘布局监听
        systemKeyboardUtils = new SystemKeyboardUtils(this, mSeamlessSwitchBottomLayout);
        systemKeyboardUtils.setOnKeyBoardListener(new SystemKeyboardUtils.OnKeyBoardListener() {
            @Override
            public void onShow(int height) {
                Log.e("TAG1231", "onShow height:" + height);
                //显示底部布局
                systemKeyboardUtils.showBottomLayout(height);
                //列表反转后滑到底部,0即为底部
                manager.scrollToPosition(0);
                //设置图片
                mSeamlessSwitchMore.setImageResource(R.drawable.svg_sms_more);
            }

            @Override
            public void onHide(int height) {
                Log.e("TAG1231", "onHide height:" + height);
                //设置图片
                mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard);
            }
        });

        //列表反转
        manager.setReverseLayout(true);
        mSeamlessSwitchRecy.setLayoutManager(manager);
        mSeamlessSwitchRecy.setAdapter(adapter);
        //列表反转后滑到底部,0即为底部
        manager.scrollToPosition(0);

        List<String> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add("数据" + i);
        }
        adapter.addData(list);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.mSeamlessSwitchMore:
                //判断软键盘是否开启
                boolean show = systemKeyboardUtils.isShow();
                Log.e("TAG1231", "show:" + show);
                if (show) {
                    //隐藏软键盘
                    systemKeyboardUtils.hideSoftInput();
                    //切换图片
                    mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard);
                } else {
                    //开启软键盘
                    systemKeyboardUtils.showSoftInput();
                    //切换图片
                    mSeamlessSwitchMore.setImageResource(R.drawable.svg_sms_more);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 触摸列表布局隐藏底部布局
     *
     * @param v
     * @param event
     * @return
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //隐藏底部布局
        boolean hideBottomLayout = systemKeyboardUtils.hideBottomLayout();
        if (hideBottomLayout) {
            //切换图片
            mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard);
        }
        return false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //移除布局监听
        systemKeyboardUtils.onDestroy();
    }

}

3.第三步 新建SystemKeyboardUtils工具类:

/**
 * 软键盘布局监听
 *
 * @author CJF
 */
public class SystemKeyboardUtils {

    /**
     * activity的根视图
     */
    private View rootView;

    /**
     * 纪录根视图的显示高度
     */
    private int rootViewVisibleHeight;

    /**
     * 判断软键盘是否开启
     */
    private boolean isShow = false;

    /**
     * 上下文
     */
    private Activity activity;

    /**
     * 需要显示与隐藏的底部布局
     */
    private View bottomLayout;

    /**
     * 动画时长
     */
    private final int animatorDuration = 300;

    private OnKeyBoardListener onKeyBoardListener;

    private final InputMethodManager imm;

    /**
     * @param activity     上下文
     * @param bottomLayout 需要显示与隐藏的底部布局
     */
    public SystemKeyboardUtils(Activity activity, View bottomLayout) {
        this.activity = activity;
        this.bottomLayout = bottomLayout;

        //获取activity的根视图
        rootView = activity.getWindow().getDecorView();

        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);

        //软键盘管理
        imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    }

    /**
     * 布局监听
     */
    private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = () -> {
        //获取当前根视图在屏幕上显示的大小
        Rect r = new Rect();
        rootView.getWindowVisibleDisplayFrame(r);
        int visibleHeight = r.height();
        if (rootViewVisibleHeight == 0) {
            rootViewVisibleHeight = visibleHeight;
            return;
        }

        //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
        if (rootViewVisibleHeight == visibleHeight) {
            return;
        }

        //根视图显示高度变小超过200,可以看作软键盘显示了
        if (rootViewVisibleHeight - visibleHeight > 200) {
            if (onKeyBoardListener != null) {
                onKeyBoardListener.onShow(rootViewVisibleHeight - visibleHeight);
            }
            rootViewVisibleHeight = visibleHeight;
            isShow = true;
            return;
        }

        //根视图显示高度变大超过200,可以看作软键盘隐藏了
        if (visibleHeight - rootViewVisibleHeight > 200) {
            if (onKeyBoardListener != null) {
                onKeyBoardListener.onHide(visibleHeight - rootViewVisibleHeight);
            }
            rootViewVisibleHeight = visibleHeight;
            isShow = false;
            return;
        }

    };

    /**
     * 判断软键盘是否开启
     *
     * @return
     */
    public boolean isShow() {
        return isShow;
    }

    /**
     * 显示底部布局
     *
     * @param height
     */
    public void showBottomLayout(int height) {
        //软键盘设置先动态设置为SOFT_INPUT_ADJUST_NOTHING 此时布局更改监听不到了
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
        //显示布局
        bottomLayout.setVisibility(View.VISIBLE);
        //更改高度
        ViewGroup.LayoutParams params = bottomLayout.getLayoutParams();
        params.height = height;
        bottomLayout.setLayoutParams(params);
        //软键盘设置最后再设置为SOFT_INPUT_ADJUST_PAN 此时布局更改又能监听到了
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    }

    /**
     * 隐藏底部布局
     */
    public boolean hideBottomLayout() {
        //底部布局隐藏与软键盘无显示的情况下 不执行
        if (bottomLayout.getVisibility() == View.GONE && !isShow()) {
            return false;
        }
        //隐藏软键盘
        hideSoftInput();
        //设置为视图不可见,但占用布局空间
        bottomLayout.setVisibility(View.INVISIBLE);
        //获取底部布局高度
        int measuredHeight = bottomLayout.getMeasuredHeight();
        //动画
        final ValueAnimator foldAnimator = ValueAnimator.ofInt(measuredHeight, 0);
        foldAnimator.setDuration(animatorDuration);
        foldAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //更改高度
                final ViewGroup.LayoutParams lp = bottomLayout.getLayoutParams();
                lp.height = (int) valueAnimator.getAnimatedValue();
                bottomLayout.setLayoutParams(lp);
            }
        });

        foldAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //底部布局隐藏
                bottomLayout.setVisibility(View.GONE);
                //软键盘设置最后再设置为SOFT_INPUT_ADJUST_RESIZE 此时布局更改又能监听到了
                activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
            }
        });
        foldAnimator.start();
        return true;
    }

    /**
     * 移除布局监听
     */
    public void onDestroy() {
        rootView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
    }

    /**
     * 隐藏软键盘
     */
    public void hideSoftInput() {
        if (imm == null) {
            return;
        }
        imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
    }

    /**
     * 开启软键盘
     */
    public void showSoftInput() {
        if (imm == null) {
            return;
        }
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

    public void setOnKeyBoardListener(OnKeyBoardListener onKeyBoardListener) {
        this.onKeyBoardListener = onKeyBoardListener;
    }

    public interface OnKeyBoardListener {
        void onShow(int height);

        void onHide(int height);
    }

}

4.第四步 新建SdkAdapter适配器类,适配一些简单的数据:

public class SdkAdapter extends BaseQuickAdapter<String, BaseViewHolder> {

    public SdkAdapter(int layoutResId) {
        super(layoutResId);
    }

    @Override
    protected void convert(BaseViewHolder helper, String item) {
        helper.setText(R.id.mOppoSdkTextPosition, String.valueOf(helper.getAdapterPosition()));
        helper.setText(R.id.mOppoSdkText, item);
    }
}

5.第五步 各个xml布局文件,以及svg图片资源文件:

//activity_seamless_switch:

<?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:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/mSeamlessSwitchRecy"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="0dp"/>

    <LinearLayout
        android:background="@drawable/background_white"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/mSeamlessSwitchMore"
                android:layout_width="0dp"
                android:layout_height="@dimen/dp_50"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:background="@drawable/background_white"
                android:padding="@dimen/dp_8"
                android:src="@drawable/svg_keyboard" />

            <EditText
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/dp_20"
                android:layout_marginTop="@dimen/dp_20"
                android:layout_marginRight="@dimen/dp_20"
                android:layout_weight="5"
                android:background="@drawable/sms_details_bg"
                android:gravity="center|left"
                android:hint="输入"
                android:maxHeight="@dimen/dp_200"
                android:minHeight="@dimen/dp_40"
                android:paddingBottom="@dimen/dp_10"
                android:paddingLeft="@dimen/dp_10"
                android:paddingTop="@dimen/dp_10"
                android:textColor="@color/black"
                android:textColorHint="@color/color_657091"
                android:textSize="@dimen/sp_15" />

        </LinearLayout>

        <TextView
            android:visibility="gone"
            android:gravity="center"
            android:text="内容布局"
            android:id="@+id/mSeamlessSwitchBottomLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</LinearLayout>

//sdk_item:

<?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="wrap_content"
    android:layout_marginBottom="@dimen/dp_5"
    android:layout_marginLeft="@dimen/dp_20"
    android:layout_marginRight="@dimen/dp_20"
    android:layout_marginTop="@dimen/dp_5"
    android:background="@drawable/selector_common_item"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/mOppoSdkTextPosition"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:background="@drawable/selector_common_item"
        android:gravity="center"
        android:minHeight="@dimen/dp_50"
        android:padding="@dimen/dp_10"
        android:text="0"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_15" />

    <TextView
        android:id="@+id/mOppoSdkText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="8"
        android:background="@drawable/selector_common_item"
        android:gravity="left|center_vertical"
        android:minHeight="@dimen/dp_50"
        android:padding="@dimen/dp_10"
        android:text="text"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_15" />

</LinearLayout>

//svg图片文件 svg_keyboard:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="#E7E9EF"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:fillColor="#ffffffff"
        android:pathData="M20,5L4,5c-1.1,0 -1.99,0.9 -1.99,2L2,17c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,7c0,-1.1 -0.9,-2 -2,-2zM11,8h2v2h-2L11,8zM11,11h2v2h-2v-2zM8,8h2v2L8,10L8,8zM8,11h2v2L8,13v-2zM7,13L5,13v-2h2v2zM7,10L5,10L5,8h2v2zM16,17L8,17v-2h8v2zM16,13h-2v-2h2v2zM16,10h-2L14,8h2v2zM19,13h-2v-2h2v2zM19,10h-2L17,8h2v2z" />
</vector>

// svg图片文件 svg_sms_more:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:alpha="0.85"
    android:autoMirrored="true"
    android:tint="#E7E9EF"
    android:viewportHeight="24"
    android:viewportWidth="24">
    <path
        android:fillColor="#ffffffff"
        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z" />
</vector>

//-----------------------------------------------------------END---------------------------------------------------------------

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做为骨干网络的分类模型的预训代码安装配置简单记录

一、安装配置环境 1、准备工作 代码地址 GitHub - bubbliiiing/classification-pytorch: 这是各个主干网络分类模型的源码&#xff0c;可以用于训练自己的分类模型。 # 创建环境 conda create -n ptorch1_2_0 python3.6 # 然后启动 conda install pytorch1.2.0 torchvision…

Anaconda环境配置Python绘图库Matplotlib的方法

本文介绍在Anaconda环境中&#xff0c;安装Python语言matplotlib模块的方法。 在之前的文章中&#xff0c;我们多次介绍了Python语言matplotlib库的使用&#xff1b;而这篇文章&#xff0c;就介绍一下在Anaconda环境下&#xff0c;配置matplotlib库的方法。 首先&#xff0c;打…

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual ...

目录 报错 解决 注意&#xff1a; - > 是追加的意思。 解决&#xff1a;分号结尾执行报错&#xff0c;然后重新输入正确的sql语句就可以了。 报错 在docker中部署mysql&#xff0c;创建进入mysql进行数据库查询的时候报错&#xff1a; ERROR 1064 (42000): You have a…

有趣的小知识(三)提升网站速度的秘诀:掌握缓存基础,让你的网站秒开

像MySql等传统的关系型数据库已经不能适用于所有的业务场景&#xff0c;比如电商系统的秒杀场景&#xff0c;APP首页的访问流量高峰场景&#xff0c;很容易造成关系型数据库的瘫痪&#xff0c;随着缓存技术的出现很好的解决了这个问题。 一、缓存的概念&#xff08;什么是缓存…

PyTorch保姆级安装教程

1 安装CUDA1.1 查找Nvidia适用的CUDA版本桌面右键&#xff0c;【打开 NVIDIA控制面板】查看【系统信息】查看NVIDIA的支持的CUDA的版本&#xff0c;下图可知支持的版本是 10.11.2 下载CUDACUDA下载官方网址https://developer.nvidia.com/cuda-toolkit-archive找到适合的版本下载…

第六章 effect.scheduler功能实现

effect.scheduler功能实现 主要先了解scheduler需要实现什么样的需求&#xff0c;有一下四点&#xff1a; 1 通过 effect 的第二个参数给定一个 scheduler 的 fn 2 effect 第一次执行的时候 还会执行 fn 3 当 响应式对象 set update 不执行fn 而是执行 scheduler 4 如果说…

面试问题【线程】

线程什么是进程什么是线程进程和线程的关系什么是并发和并行如何使用线程Thread 和 Runnable 两种开发线程的区别线程的生命周期什么是上下文切换什么是线程死锁如何避免死锁说说 sleep() 方法和 wait() 方法区别和共同点为什么我们调用 start() 方法时会执行 run() 方法&#…

Transformer学习

原论文&#xff1a;Attention Is All You Need。论文地址&#xff1a;https://arxiv.org/abs/1706.03762. Transformer是针对自然语言处理的&#xff0c;Google在2017年发表在Computation and Language&#xff0c;RNN模型记忆长度有限且无法并行化但是Tranformer解决了上述问…

解析几何北大第五版复习提纲

第一章 两向量向量积 向量积定义&#xff1a;a x b |a||b|sin几何意义&#xff1a;平行四边形面积性质&#xff1a; 两向量共线的充分必要条件是 a x b 0 数乘&#xff1a; 分配律&#xff1a; 求法&#xff1a;行列式 三向量混合积 混合积定义&#xff1a;对于一个六面体,…

快鲸SCRM发布口腔企业私域运营解决方案

口腔企业普遍面临着以下几方面运营痛点问题 1、获客成本居高不下&#xff0c;恶性竞争严重 2、管理系统落后&#xff0c;人员流失严重 3、客户顾虑多、决策时间长 4、老客户易流失&#xff0c;粘性差 以上这些痛点&#xff0c;不得不倒逼口腔企业向精细化运营客户迈进。 …

【LeetCode】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 p131 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/ 1. 题目介绍&#xff08;21. 调整数组顺序使奇数位于偶数前面&#xff09; 输入一个整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&…

4自由度串联机械臂按颜色分拣物品功能的实现

1. 功能说明 本实验要实现的功能是&#xff1a;将黑、白两种颜色的工件分别放置在传感器上时&#xff0c;机械臂会根据检测到的颜色&#xff0c;将工件搬运至写有相应颜色字样区域。 2. 使用样机 本实验使用的样机为4自由度串联机械臂。 3. 运动功能实现 3.1 电子硬件 在这个…

快速吃透π型滤波电路-LC-RC滤波器

π型滤波器简介 π型滤波器包括两个电容器和一个电感器&#xff0c;它的输入和输出都呈低阻抗。π型滤波有RC和LC两种&#xff0c; 在输出电流不大的情况下用RC&#xff0c;R的取值不能太大&#xff0c;一般几个至几十欧姆&#xff0c;其优点是成本低。其缺点是电阻要消耗一些…

亚马逊二审来袭,跨境电商传统验证算法真的靠谱吗?

多个大卖突遭二审 已有卖家账号被封 近期有不少卖家在论坛上反映称自己收到了亚马逊的二次视频验证邮件。 邮件上称&#xff1a; 卖家必须要完成额外的身份审查&#xff0c;才有资格在亚马逊继续销售商品&#xff1b;亚马逊要求卖家出示注册时提交的身份证原件和营业执照原件…

聊聊混沌工程

这是鼎叔的第五十四篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。欢迎关注本专栏和微信公众号《敏捷测试转型》&#xff0c;大量原创思考文章陆续推出。混沌工程是一门新兴学科&#xff0c;它不仅仅只是个技术活动&#xff0c;还包含如何设计能够持续协作的…

xgboost:算法数学原理

xgboost算法数学原理 1、求预测值 y^iϕ(xi)∑k1Kfk(xi),fk∈F,(1)\hat{y}_i\phi\left(\mathbf{x}_i\right)\sum_{k1}^K f_k\left(\mathbf{x}_i\right), \quad f_k \in \mathcal{F},\tag{1} y^​i​ϕ(xi​)k1∑K​fk​(xi​),fk​∈F,(1) F{f(x)wq(x)}(q:Rm→T,w∈RT)\mathca…

即时通讯开发常用加解密算法与通讯安全

平时开发工作中&#xff0c;我们会经常接触加密、解密的技术。尤其在今天移动互联网时代&#xff0c;越来越多的用户会将数据存储在云端&#xff0c;或使用在线的服务处理信息。这些数据有些涉及用户的隐私&#xff0c;有些涉及用户的财产&#xff0c;要是没有一套的方案来解决…

玩转结构体---【C语言】

⛩️博主主页&#xff1a;威化小餅干&#x1f4dd;系列专栏&#xff1a;【C语言】藏宝图&#x1f38f; ✨绳锯⽊断&#xff0c;⽔滴⽯穿&#xff01;一个编程爱好者的学习记录!✨目录结构体类型的声明结构体成员访问结构体传参前言我们是否有想过&#xff0c;为什么会有结构体呢…

stylelint执行插件的全过程

stylelint可以用来扩展插件去实现各种规则&#xff0c;接下来带大家看看stylelint是如何执行插件的 首先遍历absoluteFilePaths路径&#xff08;该路径是我们执行lint命令配置的文件类型eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix&…

Spark RDD

RDD RDD 是构建 Spark 分布式内存计算引擎的基石&#xff0c;如 &#xff1a;DAG/调度系统都衍生自 RDD RDD 是对分布式数据集的抽象&#xff0c;囊括所有内存/磁盘的分布式数据实体 RDD/数组差异 对比项数组RDD概念数据结构实体数据模型抽象数据跨度单机进程内跨进程&…