【Android】Jetpack入门知识总结(LifeCycle,ViewModel,LiveData,DataBinding等)

文章目录

  • LifeCycle
    • 使用Lifecycle解耦页面与组件
      • 自定义控件实现LifecycleObserver接口
      • 注册生命周期监听器
    • 使用LifecycleService解耦Service与组件
    • 使用ProcessLifecycleOwner监听应用程序生命周期
  • ViewModel
    • 用法
    • 在 Fragment 中使用 ViewModel
  • LiveData
  • DataBinding
    • 导入依赖
    • 基本用法
      • 在布局文件中生成
      • 使用DataBinding的布局文件
      • 要绑定的数据类
      • 在Activity使用
    • 事件绑定
      • 定义事件处理类
      • 在Activity中设置绑定
      • 布局文件
    • 使用类方法
  • BindingAdapter
    • 示例
  • 双向绑定
    • BaseObservable
      • 示例
    • ObservableField

LifeCycle

使用Lifecycle解耦页面与组件

自定义控件实现LifecycleObserver接口

这里实现一个自定义的Chronometer,并实现能够响应生命周期事件的功能

public class MyChronometer extends Chronometer implements LifecycleObserver {private long elapsedtime;public MyChronometer(Context context, AttributeSet attrs) {super(context, attrs);}// 添加注解与生命周期事件关联@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)private void startMeter() {setBase(SystemClock.elapsedRealtime() - elapsedtime);start();}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)private void stopMeter() {elapsedtime = SystemClock.elapsedRealtime() - getBase();stop();}
}

注册生命周期监听器

在代码中使用自定义组件并为其注册生命周期监听器

public class MainActivity extends AppCompatActivity {private MyChronometer chronometer;private long elapsedtime;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);chronometer = findViewById(R.id.chronometer);// 注册生命周期监听器getLifecycle().addObserver(chronometer);}
} 

activityfragment都是直接实现了LifecycleOwner接口,所以直接调用getLifecycle方法得到LifeCycle对象。addObserver 注册了一个生命周期观察者,当 MainActivity 的生命周期发生变化时,chronometer 会自动响应这些事件。

使用LifecycleService解耦Service与组件

1. 添加依赖

生命周期 | Jetpack | Android Developers (google.cn)

    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

实现了 LifecycleObserver 接口的类,用于监听 Service 的生命周期事件。

public class MyLocationObserver implements LifecycleObserver {private Context mContext;private LocationManager locationManager;private MyLocationlistener myLocationlistener;public MyLocationObserver(Context context) {this.mContext = context;}@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)public void startGetLocation() {Log.d("TagA", "start位置");if (ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {return;}locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);myLocationlistener = new MyLocationlistener();locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 1, myLocationlistener);}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)public void stopGetLocation() {Log.d("TagA", "stop位置");locationManager.removeUpdates(myLocationlistener);}static class MyLocationlistener implements LocationListener {@Overridepublic void onLocationChanged(@NonNull Location location) {Log.d("TagA", "位置变了");}}
}

扩展自 LifecycleService 的服务

public class MyLocationService extends LifecycleService {public MyLocationService() {Log.d("TagA", "MyLocationService空参构造");MyLocationObserver myLocationObserver = new MyLocationObserver(this);getLifecycle().addObserver(myLocationObserver);}
}

启动服务

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.d("TagA", "启动");Intent intent = new Intent(this, MyLocationService.class);startService(intent);} 
}

使用ProcessLifecycleOwner监听应用程序生命周期

ProcessLifecycleOwner 是 Android Jetpack 中的一个类,用于监听整个应用进程的生命周期事件。与 Activity 和 Fragment 的生命周期不同,ProcessLifecycleOwner 关注的是整个应用的前后台状态切换。它实现了 LifecycleOwner 接口,因此你可以像使用 Activity 或 Fragment 的生命周期一样,监听应用的生命周期事件。

ProcessLifecycleOwner 允许你监听以下两个主要状态:

  1. 前台:当应用至少有一个 Activity 可见时,进入前台。
  2. 后台:当所有 Activity 都不可见时,应用进入后台。
public class MyApp extends Application implements LifecycleObserver {@Overridepublic void onCreate() {super.onCreate();// 注册观察者来监听应用的生命周期ProcessLifecycleOwner.get().getLifecycle().addObserver(this);}@OnLifecycleEvent(Lifecycle.Event.ON_START)public void onEnterForeground() {Log.d("AppLifecycle", "应用进入前台");// 这里可以添加当应用进入前台时需要执行的操作}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void onEnterBackground() {Log.d("AppLifecycle", "应用进入后台");// 这里可以添加当应用进入后台时需要执行的操作}
}
  1. 继承 Application 类
    创建一个自定义的 Application 类,并在其中注册生命周期观察者。

  2. 添加生命周期观察者
    使用 ProcessLifecycleOwner.get().getLifecycle().addObserver() 来添加生命周期观察者。这样可以监听整个应用的生命周期。

  3. 处理生命周期事件
    通过 @OnLifecycleEvent(Lifecycle.Event.ON_START)@OnLifecycleEvent(Lifecycle.Event.ON_STOP) 监听应用进入前台和后台的事件。在进入前台或后台时,可以执行相应的逻辑,比如暂停或恢复任务、更新UI、数据同步等。

优点

  1. 应用级生命周期管理:不再需要逐个监听每个 Activity 或 Fragment 的生命周期事件,ProcessLifecycleOwner 提供了一种应用级别的生命周期事件处理方式。

  2. 前后台切换检测:可以用来检测应用是否进入后台或回到前台,非常适合在应用进入后台时暂停某些服务,或者在进入前台时恢复。

注意:ProcessLifecycleOwner 只监听应用的前台和后台状态,不会捕捉到具体的 Activity 或 Fragment 的生命周期事件。如果需要监听具体的页面状态,仍然需要使用各自的 LifecycleOwner

ViewModel

ViewModel 是 Android Jetpack 提供的架构组件之一,主要用于存储和管理与 UI 相关的数据,以确保在配置更改(如屏幕旋转)时数据能够持久化并且不会丢失。ViewModel 可以帮助我们更好地分离 UI 控制逻辑与数据处理逻辑,增强代码的可维护性。

  1. 生命周期感知ViewModel 是生命周期感知的,它的生命周期比 ActivityFragment 更长,因此即使 UI 控件销毁重建,数据依然可以保存。
  2. 持久化数据:它可以避免在配置更改(如屏幕旋转)时重新加载数据。
  3. UI 与数据逻辑分离:ViewModel 主要处理数据逻辑,使 UI 控制代码和业务逻辑分离,保持代码结构清晰。

用法

  1. 创建 ViewModel
  2. ActivityFragment 中创建 ViewModel 实例
  3. 使用 ViewModel 提供的数据更新 UI
import androidx.lifecycle.ViewModel;public class MyViewModel extends ViewModel {private int counter = 0;// 增加计数public void increaseCounter() {counter++;}// 获取当前计数public int getCounter() {return counter;}
}
  1. 在 Activity 中使用 ViewModel
public class MainActivity extends AppCompatActivity {private TextView textView;private MyViewModel myViewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView = (TextView) findViewById(R.id.textView);// 通过 ViewModelProvider 获取 MyViewModel 的实例myViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);textView.setText(String.valueOf(myViewModel.getCounter()));}public void plus(View view) {myViewModel.increaseCounter();textView.setText(String.valueOf(myViewModel.getCounter()));}
}

在 Fragment 中使用 ViewModel

如果是在 Fragment 中使用 ViewModel,方式与 Activity 类似,只需确保使用的是 FragmentViewModelProvider,代码如下:

myViewModel = new ViewModelProvider(getActivity()).get(MyViewModel.class);

LiveData

ViewModel 通常与 LiveData 结合使用,这样可以让 UI 自动监听数据变化并更新,而不需要手动刷新界面。

示例:

实现两个fragment中的seekbar同步变化

public class MyViewModel3 extends ViewModel {private MutableLiveData<Integer> progerss;public MutableLiveData<Integer> getProgerss() {if (progerss == null) {progerss = new MutableLiveData<Integer>();}return progerss;}
}

fragment处理

public class Fragment1 extends Fragment {private MyViewModel3 myViewModel3;public Fragment1() {}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_1, container, false);SeekBar seekBar = v.findViewById(R.id.seekBar);myViewModel3 = new ViewModelProvider(getActivity(), new ViewModelProvider.AndroidViewModelFactory()).get(MyViewModel3.class);myViewModel3.getProgerss().observe(getActivity(), new Observer<Integer>() {@Overridepublic void onChanged(Integer integer) {seekBar.setProgress(integer);}});seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {myViewModel3.getProgerss().setValue(progress);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});return v;}
}

两个fragment中都需要进行修改

实现效果:

image-20241014183933983

DataBinding

导入依赖

android {...buildFeatures {dataBinding true}
}

基本用法

在布局文件中生成

image-20241014221456001

使用DataBinding的布局文件

<?xml version="1.0" encoding="utf-8"?>
<layout 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"><data><variablename="user"type="com.example.livedatapractice.User" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.name}"android:textSize="50dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"tools:text="name" /><TextViewandroid:id="@+id/tv_age"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="67dp"android:text="@{String.valueOf(user.age)}"android:textSize="50dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.498"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/tv_name"app:layout_constraintVertical_bias="0.0"tools:text="age" /></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

要绑定的数据类

package com.example.livedatapractice;public class User {private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}
}

在Activity使用

public class MainActivity extends AppCompatActivity {private ActivityMainBinding activityMainBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);User user = new User("lixaing", 20);activityMainBinding.setUser(user);}
}

事件绑定

定义事件处理类

public class EventHandleListener {private Context context;public EventHandleListener(Context context) {this.context = context;}public void buttonOnClick(View view) {Toast.makeText(context, "点", Toast.LENGTH_SHORT).show();}
}

在Activity中设置绑定

public class MainActivity extends AppCompatActivity {private ActivityMainBinding activityMainBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);User user = new User("lixaing", 20);activityMainBinding.setUser(user);// setactivityMainBinding.setEventHandle(new EventHandleListener(this));}
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<layout 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"><data><variablename="user"type="com.example.livedatapractice.User" /><variablename="eventHandle"type="com.example.livedatapractice.EventHandleListener" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.name}".../><TextViewandroid:id="@+id/tv_age"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{String.valueOf(user.age)}".../><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button"android:onClick="@{eventHandle.buttonOnClick}".../></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

使用类方法

定义工具类

package com.example.databindingpractice2;public class StringUtils {public static String toUpperCase(String str) {return str.toUpperCase();}
}

在布局文件中使用

<data><import type="com.example.databindingpractice2.StringUtils" /><variablename="user"type="com.example.databindingpractice2.ObservableUser" />
</data>
		   <TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{StringUtils.toUpperCase(user.lastName)}" />

image-20241015204321757

BindingAdapter

有很多属性并非遵循了 javaBean 约定,例如 ImageView 可以通过android:src=“@{userViewModel.head}” 来绑定图片源,但是 ImageView 并没有提供 setSrc() 方法,而设置图片的方法是 setImageDrawable()、setImageURI() 等这些方法;但我们却也可以通过绑定,是因为google为我们提供了许多扩展标记行为的注解,帮助我们完成特殊需求下的匹配绑定,例如 @BindingAdapte可以扩展绑定行为,当然还有其他更丰富的的注解可以组合完成任何双向绑定的需求和复杂的中间过程。

示例

  1. 创建一个 BindingAdapter,将 URL 绑定到 ImageView
public class BindingAdapter {@androidx.databinding.BindingAdapter("app:src")public static void loadImage(ImageView view, String url) {Glide.with(view.getContext()).load(url).error(R.drawable.ic_launcher_background).into(view);}
}
  1. ImageView 中使用 BindingAdapter
<?xml version="1.0" encoding="utf-8"?>
<layout 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"><data><variablename="user"type="com.example.livedatapractice.User" /><variablename="eventHandle"type="com.example.livedatapractice.EventHandleListener" /><variablename="imageUrl"type="String" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity">...<ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.498"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.097"app:src="@{imageUrl}"tools:srcCompat="@tools:sample/avatars" /></androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  1. 在Activity中使用
activityMainBinding.setImageUrl(url);

当 ImageView 控件的 url 属性值发生变化时,dataBinding 就会将 ImageView 实例以及新的 url 值传递给 loadImage() 方法,从而可以在此动态改变 ImageView 的相关属性

双向绑定

BaseObservable

示例

继承BaseObservable类,

get方法使用@Bindable注解,

set方法添加notifyPropertyChanged(BR.firstName)通知绑定的视图(View)数据已经发生了变化,需要更新视图显示的内容

// 被观察者    viewModel
public class ObservableUser extends BaseObservable {private String firstName;private String lastName;public ObservableUser(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}@Bindablepublic String getFirstName() {return firstName;}@Bindablepublic String getLastName() {return lastName;}public void setFirstName(String firstName) {this.firstName = firstName;notifyPropertyChanged(BR.firstName);}public void setLastName(String lastName) {this.lastName = lastName;notifyPropertyChanged(BR.lastName);}
}

布局文件中采用@=符号,这里允许EditTextuser.firstName之间进行双向数据同步。

<?xml version="1.0" encoding="utf-8"?>
<layout 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"><data><variablename="user"type="com.example.databindingpractice2.ObservableUser" /></data><LinearLayoutandroid:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.lastName}"android:textSize="30dp" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.firstName}"android:textSize="30dp" /><EditTextandroid:id="@+id/et"android:layout_width="186dp"android:layout_height="54dp"android:text="@={user.lastName}"android:textSize="30dp" /><EditTextandroid:id="@+id/et2"android:layout_width="186dp"android:layout_height="54dp"android:text="@={user.firstName}"android:textSize="30dp" /></LinearLayout>
</layout>

在主活动中将user对象与视图绑定

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);ObservableUser user = new ObservableUser("Yuyu","Feng");binding.setUser(user);}
}

ObservableField

与直接继承 Observable 类相比,ObservableField 更适合简单场景下的单一数据绑定,不需要复杂的通知操作,可以理解为官方对 BaseObservable 中字段的注解和刷新等操作的封装。Android 为常见的基本数据类型(如 intboolean 等)提供了对应的 ObservableX 类型,方便开发者使用。

ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble

BaseObservable的示例修改

public class ObservableUser {private ObservableField<String> firstName;private ObservableField<String>  lastName;public ObservableUser(String firstName, String lastName) {this.firstName = new ObservableField<>(firstName);this.lastName = new ObservableField<>(lastName);}public ObservableField<String> getFirstName() {return firstName;}public void setFirstName(ObservableField<String> firstName) {this.firstName = firstName;}public ObservableField<String> getLastName() {return lastName;}public void setLastName(ObservableField<String> lastName) {this.lastName = lastName;}
}


感谢您的阅读
如有错误烦请指正


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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024_E_100_连续字母长度

连续字母长度 题目描述 给定一个字符串&#xff0c;只包含大写字母&#xff0c;求在包含同一字母的子串中&#xff0c;长度第 k 长的子串的长度&#xff0c;相同字母只取最长的那个子串。 输入描述 第一行有一个子串(1<长度<100)&#xff0c;只包含大写字母。 第二行为…

傅里叶分析之掐死教程(完整版)更新于2014.06.06

作 者&#xff1a;韩 昊 知 乎&#xff1a;Heinrich 微 博&#xff1a;花生油工人 知乎专栏&#xff1a;与时间无关的故事 谨以此文献给大连海事大学的吴楠老师&#xff0c;柳晓鸣老师&#xff0c;王新年老师以及张晶泊老师。 转载的同学请保留上面这句话&#xff0c;谢谢。如果…

stable diffusion WEBUI Brief summary

1&#xff0c;rembg(去除背景-》蒙版) import rembg from PIL import Image, ImageOps import numpy as np# 打开图像 input_path "./p_6258838.jpg" input_image Image.open(input_path)# 移除背景&#xff0c;得到带有透明背景的图像 output_image rembg.remove…

IO编程--两进程间的实时通信

一、使用有名管道实现两个进程之间的相互通信 代码如下&#xff1a; 创建有名管道文件 #include <myhead.h> int main(int argc, const char *argv[]) {if(mkfifo("myfifo",0664)-1){perror("create error");return -1;}if(mkfifo("myfifo_1&qu…

UDP/TCP协议详解

目录 一,自定义应用层协议: 1)xml 2),JSON 3),yml 4),google protobuffer 二,传输层UDP/TCP: UDP协议: TCP协议: TCP的核心机制一:确认应答 TCP核心机制二:超时重传 TCP核心机制三:连接管理 TCP核心机制四:滑动窗口 TCP核心机制五:流量控制 TCP核心机制六:拥塞控制…

基于springboot的网上服装购物商城系统

基于springboot的网上服装购物商城系统 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a; &#x…

Video-LLaMA论文解读和项目部署教程

Video-LLaMA: An Instruction-tuned Audio-Visual Language Model for Video Understanding 相关工作 大型语言模型: 本文的工作基于这些LLM,并提供即插即用插件,使其能够理解视频中的视觉和听觉内容。 多模态大型语言模型: 现有的方法可以分为两大类。 第一类包括使用LL…

【Word原件测试资料合集】软件系统功能测试方案,软件测试方案(整体方案),软件测试文档-测试计划模版(功能与性能),软件测试流程

一、 前言 &#xff08;一&#xff09; 背景 &#xff08;二&#xff09; 目的 &#xff08;三&#xff09; 测试目标 &#xff08;四&#xff09; 适用范围与读者对象 &#xff08;五&#xff09; 术语与缩写 二、 软件测试实施流程 &#xff08;一&#xff09; 测试工作总体流…

stm32驱动W2812

W2812简介 W2812 内置有控制电路和 RGB LED 灯珠&#xff0c;用户只需通过一条数据线进行控制 每一个LED的R、G、B分别由八位数据控制颜色浓度&#xff0c;&#xff08;每种颜色浓度有0~255档&#xff0c;理论上RGB就可以组成256的3次方中颜色组合&#xff09;即每个LED需要…

基于MATLAB的混沌序列图像加密程序

设计目的 图像信息生动形象&#xff0c;它已成为人类表达信息的重要手段之一&#xff0c;网络上的图像数据很多是要求发送方和接受都要进行加密通信&#xff0c;信息的安全与保密显得尤为重要&#xff0c;因此我想运用异或运算将数据进行隐藏&#xff0c;连续使用同一数据对图…

【Eclipse系列】解决Eclipse中xxx.properties文件中文乱码问题

问题描述&#xff1a;由于eclipse对Properties资源文件的编码的默认设置是ISO-8859-1&#xff0c;所以在打开.properties文件时&#xff0c;会发现中文乱码了&#xff0c;如图&#xff1a; 解决方法&#xff1a; 1、一次生效法 右击该properties文件–>properties–>Re…

力扣2653.滑动窗口的美丽值

给你一个长度为 n 的整数数组 nums &#xff0c;请你求出每个长度为 k 的子数组的 美丽值 。 一个子数组的 美丽值 定义为&#xff1a;如果子数组中第 x 小整数 是 负数 &#xff0c;那么美丽值为第 x 小的数&#xff0c;否则美丽值为 0 。 请你返回一个包含 n - k 1 个整数…

__问题——进入启动文件_卡死在Default_Handler_死机

MCU&#xff1a;STM32F407VET6 先说结论&#xff0c;调试时跳转到启动文件里的死循环&#xff0c;只要不是硬件错误中断&#xff0c;那么多半是因为中断处理函数没有定义导致的。 【历程】 今天在测试最小单片机系统时&#xff0c;定义了一个按键处理&#xff0c;依赖的是外部中…

全网免费的文献调研方法以及获取外网最新论文、代码和翻译pdf论文的方法(适用于硕士、博士、科研)

1. 文献调研 学术搜索引擎(十分推荐前三个&#xff0c;超有用)&#xff1a;使用 Google Scholar(https://scholar.google.com/)(https://scholar.google.com.tw/)(巨人学术搜索‬‬)、&#xff08;三个都可以&#xff0c;镜像网站&#xff09; arXiv(https://arxiv.org/)、&am…

【python】OpenCV—Sort the Point Set from Top Left to Bottom Right

文章目录 1、功能描述2、代码实现3、效果展示4、更多例子5、参考 1、功能描述 给出一张图片&#xff0c;里面含有各种图形&#xff0c;取各种图形的中心点&#xff0c;从左到右从上到下排序 例如 2、代码实现 import cv2 import numpy as npdef process_img(img):img_gray c…

【计算机网络原理】GBN,SR,TCP区别以及案例介绍

概念介绍 GBN、SR和TCP协议的主要区别在于它们的重传机制、确认方式以及缓存机制的不同。‌ GBN&#xff08;Go-Back-N&#xff09;协议在数据传输中&#xff0c;如果某个报文段没有被正确接收&#xff0c;那么从这个报文段到后面的所有报文段都需要重新发送。GBN采用累计应答…

网络安全基础知识点_网络安全知识基础知识篇

文章目录 一、网络安全概述1.1 定义1.2 信息安全特性1.3 网络安全的威胁1.4 网络安全的特征 二、入侵方式2.1 黑客2.1.1 入侵方法2.1.2 系统的威胁2.2 IP欺骗与防范2.2.1 TCP等IP欺骗基础知识2.2.2 IP欺骗可行的原因2.2.3 IP欺骗过程2.2.4 IP欺骗原理2.2.5 IP欺骗防范2.3 Sniff…

Verilator——最简单、最细节上手教程

目录 前言工具安装Verilator 安装GTKwave 安装 Verilator 基础用法fst格式和vcd格式的wave文件Verilator 的使用 Verilator 的进阶使用与GDB搭配与makefile搭配 Verilator 的高阶用法访问模块内部数据 前言 此教程会以ubuntu22.04为例 从如何安装&#xff0c;到如何使用 全程帮…

双十一购物节有哪些好物值得入手?2024双十一好物清单合集分享

一年一度的双十一购物狂欢节即将来临&#xff0c;各大平台纷纷开启预热活动&#xff0c;伴随着品牌的疯狂折扣和满减优惠&#xff0c;众多商品即将迎来超值的价格。现在正是大家“剁手”换新装备的大好时机。作为一名深耕智能产品多年的资深达人&#xff0c;今天这期我将从不同…