Android开发—Jetpack四件套

news2024/11/15 17:31:14

2017年,Google发布了Android Architecture Components,包括Room、LiveData、ViewModel和Paging等组件,旨在帮助开发者更轻松地实现MVVM架构。

2018年,Google在I/O大会上推出的一套Android开发组件库,旨在帮助开发者更轻松、更高效地构建Android应用。

随着时间的推移,Android Jetpack不断地更新和增加新的组件,使得Android应用的开发更加高效、稳定和可维护。

今天的主题主要分为三个维度。第一个维度是4W2H分析Jetpack,第二个维度是Jetpack四件套。第三个维度是总结与展望。

其中,4W2H分析Jetpack主要针对Jetpack提出了6个高价值问题。

其中,Jetpack四件套列举了LifeCycle、LiveData、ViewModel和DataBing四种常见的Jetpack工具包。

一、什么场景下使用Jetpack?

Jetpack适用于开发各种类型的Android应用程序,包括单页面应用程序、多页面应用程序、后台任务应用程序等。下面是一些适合使用Jetpack的场景:

  1. 构建大型应用程序:Jetpack提供了一些库,如ViewModel、LiveData和Navigation,可以帮助开发者更好地管理应用程序的生命周期、状态和导航,使得构建大型应用程序更加容易。
  2. 处理后台任务:Jetpack中的WorkManager库提供了一种简单、可靠的方式来管理后台任务,如数据同步、推送通知、文件上传等。
  3. 数据库访问:Jetpack中的Room库提供了一个抽象层,可以让开发者方便地访问和管理SQLite数据库,使得数据存储和访问更加容易。
  4. 响应式编程:Jetpack中的LiveData和Data Binding库提供了响应式编程的功能,可以让数据在数据源发生变化时自动更新UI,提高应用程序的性能和可靠性。
  5. 代码重用:Jetpack中的各种库都旨在解决Android应用程序开发中的常见问题,并提供一致的API和开发体验,使得代码重用更加容易。

二、为什么使用Jetpack?

以下是使用Jetpack的一些好处:

  1. 更好的代码组织和可维护性:Jetpack提供了一组库,这些库旨在解决Android应用程序开发中的常见问题,如生命周期管理、数据存储、后台任务处理等。使用Jetpack可以使代码更加模块化,易于维护。
  2. 更好的代码可读性:Jetpack提供了一致的API和开发体验,可以使代码更加易于理解和阅读。
  3. 更好的开发效率:Jetpack提供了一些库和工具,如Navigation和Data Binding,可以帮助开发者更快地开发Android应用程序,提高开发效率。
  4. 更好的性能和可靠性:Jetpack中的一些库,如LiveData和WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和可靠性。
  5. 更好的向后兼容性:Jetpack中的一些库,如ViewModel和LiveData,提供了对Android不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的Android系统的应用程序。 综上所述,Jetpack可以帮助开发者更好地组织代码、提高开发效率、提高应用程序的性能和可靠性,并提供了对不同版本的Android系统的向后兼容性支持。

三、什么样的团队该使用Jetpack?

Jetpack适用于各种规模的Android开发团队,特别是那些希望提高应用程序质量、开发效率和可维护性的团队。以下是一些团队适合使用Jetpack的场景:

  1. 大型团队:Jetpack提供了一致的API和开发体验,可以使大型团队更容易协作开发,提高团队的开发效率和代码质量。
  2. 跨职能团队:Jetpack提供了一些库和工具,如Navigation和Data Binding,可以帮助开发者更快地开发Android应用程序,使得跨职能团队之间更容易协作。
  3. 需要提高应用程序性能和可靠性的团队:Jetpack中的一些库,如LiveData和WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和可靠性。
  4. 需要提高代码可维护性的团队:Jetpack提供了一些库,如ViewModel和Room,可以帮助开发者更好地管理应用程序的状态和数据,使得代码更易于维护。
  5. 需要保持向后兼容性的团队:Jetpack中的一些库,如ViewModel和LiveData,提供了对Android不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的Android系统的应用程序。 综上所述,Jetpack适合各种规模和类型的Android开发团队,特别是那些希望提高应用程序质量、开发效率和可维护性的团队。

四、怎样使用Jetpack?

以下是使用Jetpack的一般步骤:

  1. 添加Jetpack库:Jetpack库可以通过在build.gradle文件中添加依赖项的方式进行添加。例如,添加Lifecycle库的依赖项:
  dependencies {
      def lifecycle_version = "2.3.1"// ViewModel
      implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"// LiveData
      implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"// Lifecycle
      implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
  }

使用Jetpack库:在添加Jetpack库后,就可以在应用程序中使用Jetpack库提供的功能了。例如,使用ViewModel库创建一个ViewModel类:


   import androidx.lifecycle.ViewModel

   class MyViewModel : ViewModel() {
       // Add ViewModel logic here
   }

结合Jetpack组件使用:Jetpack库提供的组件可以结合使用,以提高应用程序的开发效率和可维护性。例如,使用ViewModel库和LiveData库实现一个响应式的用户界面:

  
    class MyActivity : AppCompatActivity() {

        private lateinit var viewModel: MyViewModel

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_my)

            // Get a reference to the ViewModel
            viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

            // Observe a LiveData object in the ViewModel
            viewModel.someData.observe(this, Observer {
                // Update the UI with the new data
            })
        }
    }

以上是使用Jetpack的一般步骤。需要根据具体的Jetpack库和应用程序需求进行相应的配置和代码实现。

五、 使用Jetpack业务价值

使用Jetpack可以带来以下业务价值:

  1. 提高开发效率:Jetpack提供了一些开发工具和库,例如ViewModel、LiveData和Room,可以减少重复的编写代码,简化开发流程,并提高开发效率。
  2. 提高应用程序质量:Jetpack提供了一致的API和开发体验,可以减少由于人为因素引起的代码错误,提高应用程序的质量。
  3. 提高应用程序性能:Jetpack中的一些库,例如Lifecycle和WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和响应速度。
  4. 简化应用程序架构:Jetpack提供了一些组件和库,例如ViewModel和Data Binding,可以帮助开发者更好地管理应用程序的状态和数据,并简化应用程序的架构。
  5. 支持向后兼容性:Jetpack中的一些库,例如ViewModel和LiveData,提供了对Android不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的Android系统的应用程序。

综上所述,使用Jetpack可以带来多种业务价值,可以提高应用程序的质量、性能和开发效率,同时简化应用程序架构和支持向后兼容性,可以使应用程序更易于维护和升级。

六、Jetpack四件套

6.1 LifeCycle

在这里插入图片描述

6.1.1 LifeCycle基础定义

Android Jetpack Lifecycle是Android Jetpack组件库中的一部分,Lifecycle是基于Android Framework中的Lifecycle概念而构建的。

Lifecycle提供了一种轻松管理组件(如Activity和Fragment)生命周期的方式,同时也支持自定义组件的生命周期。

Jetpack Lifecycle提供了一组类和接口,使得开发者可以在组件的生命周期各个阶段执行相应的操作。

这些类和接口包括:

  • LifecycleOwner: 拥有生命周期的对象,通常是Activity和Fragment。

  • LifecycleObserver: 监听组件的生命周期事件的观察者对象。

  • Lifecycle: 组件的生命周期,包括CREATED、STARTED、RESUMED、PAUSED、STOPPED、DESTROYED等状态。

  • LiveData: 一个可观察的数据容器,可以在组件生命周期的不同阶段更新数据。

使用Jetpack Lifecycle,可以更容易地避免内存泄漏和其他生命周期相关的问题。

例如,可以在组件被销毁时自动释放资源、取消网络请求等操作。

此外,Jetpack Lifecycle还提供了一种方式来创建自定义的生命周期状态,以更好地满足App的需求。

总之,Jetpack Lifecycle是Android Jetpack组件库中的一个重要组件,可以帮助开发者更轻松地管理组件的生命周期,从而提高App的质量和性能。

6.1.2 LifeCycle基础使用

在App的主Activity中实现一个简单的计时器,当Activity处于前台时,计时器会不断递增,当Activity被销毁时,计时器将停止。

具体实现步骤如下:

  1. 在gradle文件中添加Jetpack组件库的依赖。

dependencies {
    implementation "androidx.lifecycle:lifecycle-extensions:2.4.0"
}
  1. 创建一个名为Timer的Java类,并实现LifeCycleObserver接口。

public class Timer implements LifecycleObserver {
    private Handler handler;
    private int seconds = 0;

    @OnLifecycleEvent(Lifecycle.Event.ON_START)public void startTimer() {
        handler = new Handler();
        handler.post(new Runnable() {
            @Overridepublic void run() {
                Log.d("Timer", "Seconds: " + seconds);
                seconds++;
                handler.postDelayed(this, 1000);
            }
        });
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void stopTimer() {
        handler.removeCallbacksAndMessages(null);
        handler = null;
    }
}
  1. 在MainActivity中添加LifecycleOwner,并在onCreate方法中添加Observer。

public class MainActivity extends AppCompatActivity {

    @Overrideprotected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获取LifecycleOwner对象LifecycleOwner lifecycleOwner = this;

        // 将Timer实例添加为Observer
        getLifecycle().addObserver(new Timer());

        // ...
    }

    // ...
}

这样,当Activity处于前台时,Timer实例中的startTimer方法会被调用,计时器会开始递增;

当Activity被销毁时,Timer实例中的stopTimer方法会被调用,计时器会停止。

这个例子展示了如何使用Jetpack LifeCycle组件来管理App组件的生命周期。

当App中存在需要在组件生命周期不同阶段执行的操作时,使用LifeCycle可以更方便地实现这些操作,同时避免了一些常见的生命周期问题

6.1.3 LifeCycle优势劣势

优势

  • 管理生命周期方便
    • 使用LifeCycle组件可以更方便地管理App组件的生命周期,避免了一些常见的生命周期问题,如内存泄漏和空指针异常等。
  • 模块化编程
    • 使用LifeCycle组件可以将App的业务逻辑分解为模块化的组件,每个组件负责管理自己的生命周期,便于代码复用和维护。
  • 规范化编程
    • 使用LifeCycle组件可以规范化App的开发,使代码更易于阅读、理解和维护。
  • 支持多个组件
    • LifeCycle组件支持多个组件进行生命周期管理,可以轻松地在多个组件之间共享状态和数据。

劣势

  • 需要继承LifecycleObserver:在实现LifeCycle功能的时候,需要继承LifecycleObserver接口,这会导致代码的继承关系稍微有点复杂。
  • 需要添加注释:在使用LifeCycle组件的时候,需要添加一些注释来指示方法是在什么时候被调用,否则可能会出现一些难以诊断的问题。

6.1.4 LifeCycle应用场景

Jetpack LifeCycle组件的实际开发应用场景包括:

  1. Activity和Fragment生命周期管理:使用LifeCycle组件可以更方便地管理Activity和Fragment的生命周期,避免了一些常见的生命周期问题,如内存泄漏和空指针异常等。
  2. 后台服务管理:使用LifeCycle组件可以更方便地管理后台服务的生命周期,可以在App退出后自动停止后台服务,避免了一些不必要的资源浪费。
  3. 数据库连接管理:使用LifeCycle组件可以更方便地管理数据库连接的生命周期,可以在App退出时自动关闭数据库连接,避免了一些不必要的资源浪费。
  4. 网络请求管理:使用LifeCycle组件可以更方便地管理网络请求的生命周期,可以在Activity或Fragment销毁时自动取消网络请求,避免了一些不必要的网络请求。
  5. 视图控制器管理:使用LifeCycle组件可以更方便地管理视图控制器的生命周期,可以在Activity或Fragment销毁时自动清除视图控制器的状态,避免了一些不必要的状态保存和恢复操作。

6.1.5 LifeCycle原理分析

类图

LifecycleOwner表示拥有生命周期的组件,比如Activity和Fragment。

Lifecycle表示组件的生命周期,LifecycleObserver表示一个组件的生命周期观察者。

LifecycleRegistry是Lifecycle接口的一个实现类,它维护了一个生命周期状态机,用于记录组件的生命周期状态和生命周期事件。

LifecycleRegistry提供了一系列方法,用于管理组件的生命周期状态和生命周期事件。当组件的生命周期事件发生变化时,LifecycleRegistry会自动更新状态机,并通知所有的LifecycleObserver观察者对象,以便它们可以相应地更新自己的状态。

LifecycleOwner可以通过getLifecycle()方法获取到一个Lifecycle对象,然后将自己的生命周期观察者对象添加到Lifecycle对象中,从而实现对组件生命周期的监听。

当组件的生命周期事件发生变化时,Lifecycle会自动通知所有的生命周期观察者对象,以便它们可以相应地更新自己的状态。
在这里插入图片描述

源码

Lifecycle库的核心是Lifecycle接口和LifecycleObserver接口。

Lifecycle接口定义了一组方法,用于将LifecycleOwner与LifecycleObserver进行关联。

public abstract class Lifecycle {
    //添加观察者
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);
    //移除观察者
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    //获取当前状态
    public abstract State getCurrentState();

//生命周期事件,对应Activity生命周期方法
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY  //可以响应任意一个事件
    }
    
    //生命周期状态. (Event是进入这种状态的事件)
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;

        //判断至少是某一状态
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

LifecycleObserver接口定义了一组回调方法,用于接收LifecycleOwner的生命周期事件。

在Lifecycle库的实现中,Lifecycle接口有两个重要的实现类,分别是LifecycleRegistry和LifecycleOwner。

LifecycleRegistry实现了Lifecycle接口,并提供了一组方法,用于管理LifecycleOwner的生命周期状态。

LifecycleOwner是一个接口,用于标识拥有生命周期状态的对象,通常是Activity或Fragment。

//androidx.activity.ComponentActivity,这里忽略了一些其他代码,我们只看Lifecycle相关
public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner{
    ...
   
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    ...
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);
        ReportFragment.injectIfNeededIn(this); //使用ReportFragment分发生命周期事件
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }
    @CallSuper
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Lifecycle lifecycle = getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
        }
        super.onSaveInstanceState(outState);
        mSavedStateRegistryController.performSave(outState);
    }

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

在LifecycleRegistry中,有一个名为mObserverMap的成员变量,用于存储LifecycleObserver对象和其关联的EventObserver对象。

当LifecycleOwner的生命周期状态更改时,LifecycleRegistry会自动调用mObserverMap中与之相关联的EventObserver对象的相应方法,以便它们可以执行适当的操作。

//LifecycleRegistry.java
   //系统自定义的保存Observer的map,可在遍历中增删
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap = new FastSafeIterableMap<>();
            
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);//获取event发生之后的将要处于的状态
        moveToState(next);//移动到这个状态
    }

    private void moveToState(State next) {
        if (mState == next) {
            return;//如果和当前状态一致,不处理
        }
        mState = next; //赋值新状态
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            return;
        }
        mHandlingEvent = true;
        sync(); //把生命周期状态同步给所有观察者
        mHandlingEvent = false;
    }
    
        private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
        while (!isSynced()) {  //isSynced()意思是 所有观察者都同步完了
            mNewEventOccurred = false;
            //mObserverMap就是 在activity中添加observer后 用于存放observer的map
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }
    ...
    
     static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

LifecycleRegistry还提供了一组方法,如handleLifecycleEvent()、getCurrentState()、addObserver()、removeObserver()等,用于管理组件的生命周期状态和LifecycleObserver对象。

在Lifecycle库的实现中,还有一些其他的类和接口,如GenericLifecycleObserver、FullLifecycleObserver、LifecycleEvent、EventObserver等,它们都是用于管理和处理组件生命周期事件的。

6.1.6 LifeCycle注意事项

3.1.6.1 不要在 onCreate() 方法中使用 Lifecycle 组件

Lifecycle 组件在 onCreate() 方法中尚未初始化完成,因此在该方法中使用它们可能会导致崩溃或不可预测的行为。建议在 onStart() 方法中使用 Lifecycle 组件。

3.1.6.2 不要手动调用 onDestroy() 方法

手动调用 onDestroy() 方法会破坏 Lifecycle 组件的生命周期,从而导致应用程序行为异常。Lifecycle 组件应该由系统自动管理,应该避免手动干预。

3.1.6.3 避免在 Fragment 中使用多个 LifecycleOwner

Fragment 自身就是一个 LifecycleOwner,因此不应该在 Fragment 中创建其他的 LifecycleOwner。这样会导致多个 LifecycleOwner 之间的状态不同步,从而导致应用程序出现问题。

篇幅原因没有展示完整

可以 点击 “此处” 即可 免费获取 学习资料 以及 更多Android学习笔记+源码解析+面试视频

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

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

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

相关文章

Python 小型项目大全 56~60

五十六、质数 原文&#xff1a;http://inventwithpython.com/bigbookpython/project56.html 质数是只能被 1 和它自己整除的数。质数有各种各样的实际应用&#xff0c;但是没有算法可以预测它们&#xff1b;我们必须一次计算一个。然而&#xff0c;我们知道有无限多的质数有待发…

技术招聘漫谈 | Java工程师招聘难?你可能需要这份独家指南

两周前&#xff0c;我们发布了一篇关于怎样招聘前端工程师的文章&#xff08;点击此处顾&#xff09;。在文章中&#xff0c;我们分析了前端岗位有哪些必不可少的考察要点&#xff0c;以及如何在面试中考核对方是否能写出高质量的代码&#xff0c;这篇文章得到了大量技术面试官…

高完整性系统工程(四): An Overview of Alloy

目录 1. 概述 2. 指定软件设计 3. 验证设计规范 4. 验证预期属性 1. 概述 在第一章中&#xff0c;我们将解释如何使用 Alloy 来探索一个非常简单的软件组件的设计&#xff0c;即大多数操作系统中存在的众所周知的垃圾箱 或回收站。目的是对如何使用 Alloy 指定和分析软件设…

MyBatis注解开发---实现自定义映射关系和关联查询

目录 一、使用注解实现自定义映射关系 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 二、使用注解实现一对一关联查询 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 三、使用注解实现一对多关联查询 1. 编写注解方法 2. 编写测试方法 3. 查看运行结果 四…

List接口中的ArrayList与LinkedList

ArrayList ArrayList的继承实现关系图 ArrayList 底层就是⼀个 Object[] 数组&#xff0c;当实例化ArrayList时没有指定数组容量大小&#xff0c;、第⼀次添加元素&#xff08;调⽤ add() ⽅法&#xff09;时会初始化为⼀个⻓度为 10 的数组&#xff08;即默认初始化容量为 1…

[Netty源码] ByteBufAllocator内存管理器相关问题 (十一)

文章目录1.ByteBufAllocator 内存管理器2.UnpooledByteBufAllocator2.1 heap内存的分配2.2 direct内存的分配3.PooledByteBufAllocator3.1 heap内存和direct内存的分配3.2 directArena分配direct内存的流程3.3 内存规格的介绍4.缓存的相关问题4.1 缓存的数据结果4.2 命中缓存的…

一维差分思想【算法推导、深刻思考】

797. 差分 - AcWing题库 差分本质上就是前缀和的逆运算 算法推导 其实在最开始自己去完成这个题目的时候&#xff0c;感觉好像是可以往前缀和方向靠的&#xff0c;但是一下子没有想到实现方法就无疾而终了。所以最后选择的算法就只是单纯的暴力&#xff08;虽然知道过不了&…

【操作系统复习】第5章 存储器管理

存储器的层次结构 存储层次 ➢ CPU寄存器 ➢ 主存&#xff1a;高速缓存、主存储器、磁盘缓存 ➢ 辅存&#xff1a;固定磁盘、可移动介质 层次越高&#xff0c;访问速度越快&#xff0c;价格也越高&#xff0c;存储容量也最小 寄存器和主存掉电后存储的信息不再存在&a…

2024软件工程考研之《软件工程导论》专业课复习

一、考察《软件工程导论》的学校 截止目前&#xff0c;考察《软件工程导论》的学校主要有&#xff1a; 大连理工大学887 北京航天航空大学991 北京交通大学901 河海大学846 海南大学835 新疆大学841 成都信息工程大学809 长安大学846 天津工业大学840 华东交通大学837 大连交通…

采购招投标系统-高效管控招采流程-降低采购成本

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

软考证书找工作有用吗?软考找工作用处大吗

软考证书是衡量IT技术人才能力的一种重要评价标准。 一、软考高级证书对找工作的帮助 1. 竞争力增强 软考高级证书具有一定难度和较高的专业技能要求&#xff0c;拥有该证书的人的技术水平和专业能力会得到认可和尊重&#xff0c;从而增强求职者的竞争力。 2. 拓宽职业发展…

防火墙NAT实验,双机热备实验

目录 NAT防火墙基础实验 源地址转换 服务器映射 域内双向NAT 域间双向NAT 双机热备基础实验 主备备份 负载分担 NAT防火墙基础实验 实验拓扑&#xff1a; 1.进入防火墙图形化页面进行配置 接口列表的配置 源地址转换 企业内部网络访问外部网络&#xff0c;进行源地…

如何用nodejs构造一个网站爬虫

爬虫是个什么东西 英文spider&#xff0c;网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些…

干货分享 | 采购没“云”和有云的区别有哪些?

多年前&#xff0c;提起“云”这个词&#xff0c;很多人还是“不知所云”。 但如今&#xff0c;大众对“云”的了解和认可程度也越来越高&#xff0c;尽情享受着“云”带来的便利。 通过“云”&#xff0c;可以随时随地畅听海量音乐、进行网购、访问云盘的照片和视频、在云端创…

【数据分析】——分析方法

上司要你帮忙看看公司最近的网站运营情况怎么样&#xff1f; 公司最近的网站运营情况&#xff1f;这个问题太宽泛了&#xff0c;你得要知道上司的明确需求 问题1:boss,你是想看看公司网站具体哪方面的问题&#xff1f; 回答&#xff1a;公司最近销售不太好&#xff0c;订单转…

Kubernetes 多集群网络方案系列 1 -- Submariner 介绍

Submariner 是一个完全开源的项目&#xff0c;可以帮助我们在不同的 Kubernetes 集群之间&#xff08;无论是在本地还是云端&#xff09;实现网络通信。Submariner 有以下功能&#xff1a; 跨集群的 L3 连接跨集群的服务发现Globalnet 支持 CIDR 重叠提供命令行工具 subctl 简…

MappedByteBuffer 详解(图解+秒懂+史上最全)

背景&#xff1a; 在尼恩视频版本里&#xff0c;从架构师视角&#xff0c;尼恩为大家彻底介绍 rocketmq 高可用、高并发中间件的原理与实操。 给大家底层的解读清楚 rocketmq 架构设计、源码设计、工业级高可用实操&#xff0c;含好多复杂度非常高、又非常核心的概念&#xff…

Python 小型项目大全 11~15

十一、标题党生成器 原文&#xff1a;http://inventwithpython.com/bigbookpython/project11.html 我们的网站需要欺骗人们去看广告&#xff01;但是想出有创意的原创内容太难了。幸运的是&#xff0c;有了标题党生成器&#xff0c;我们可以让一台计算机产生数百万个令人发指的…

在CentOS 7.5上用离线压缩包安装Python-3.9.10的过程记录

项目的需要&#xff0c;需要在CentOS 7.5上去部署一个Python 3.9.10的安装环境。 值得注意的是在CentOS 7.5系统中&#xff0c;默认安装了 Python 2.7.x。 Python 2.7.x 是许多系统工具和应用程序所依赖的版本&#xff0c;因此它被包括在 CentOS 7.5 发行版中。如果在 CentOS …

太全面了,数据治理8大核心模块建设参考

数据治理是一个去中心化、多元参与的系统工程。一个全面且明确的数据治理体系&#xff0c;可以帮助组织构建生态式、协同化治理路径&#xff0c;最大化地提升整体数据质量&#xff0c;实现数据战略&#xff0c;激活新型生产力。 本文以元数据、数据标准、主数据、数据交换、数…