Android学习进阶

UI组件进阶

使用RecyclerView和Adapter显示列表数据

RecyclerView是Android开发中用于显示列表数据的一个灵活且高效的组件。与其前身ListView相比,RecyclerView引入了更加复杂的布局排列和动画支持,使得创建高度定制化的列表和网格布局变得更加简单。使用RecyclerView需要配合Adapter来显示数据。以下是实现RecyclerView显示列表数据的基本步骤:

1. 添加RecyclerView依赖

首先,确保你的项目中包含了RecyclerView库。打开你的build.gradle(Module: app)文件,并添加以下依赖:

dependencies {implementation 'androidx.recyclerview:recyclerview:1.2.1'
}

请检查是否有最新版本的RecyclerView依赖可用,并使用最新版本。

2. 添加RecyclerView到布局文件

在你的布局文件中添加RecyclerView组件。例如,在activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/my_recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"/>

3. 创建列表项布局

RecyclerView中每个项(item)创建一个布局文件。例如,创建一个item_view.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="wrap_content"android:orientation="horizontal"android:padding="16dp"><TextViewandroid:id="@+id/item_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="18sp"/>
</LinearLayout>

4. 创建Adapter

创建一个Adapter类继承自RecyclerView.Adapter,并实现必要的方法:onCreateViewHolder(), onBindViewHolder(), getItemCount()。这个Adapter负责将数据绑定到每个ViewHolder中。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {private String[] mDataset;// 提供合适的构造器(取决于数据集的类型)public MyAdapter(String[] myDataset) {mDataset = myDataset;}// 创建新视图(由布局管理器调用)@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {// 创建一个新视图View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);return new MyViewHolder(itemView);}// 替换视图的内容(由布局管理器调用)@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) {// 获取元素数据集在这个位置的数据,并替换视图的内容holder.textView.setText(mDataset[position]);}// 返回数据集的大小(由布局管理器调用)@Overridepublic int getItemCount() {return mDataset.length;}// 提供对视图的引用public static class MyViewHolder extends RecyclerView.ViewHolder {public TextView textView;public MyViewHolder(View itemView) {super(itemView);textView = itemView.findViewById(R.id.item_text);}}
}

5. 在Activity中使用RecyclerView

在你的Activity中设置RecyclerViewAdapter

public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private RecyclerView.Adapter adapter;private RecyclerView.LayoutManager layoutManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.my_recycler_view);// 使用这个设置来提高性能,如果你知道内容不会改变布局大小recyclerView.setHasFixedSize(true);// 使用线性布局管理器layoutManager = new LinearLayoutManager(this);recyclerView.setLayoutManager(layoutManager);// 指定adapteradapter = new MyAdapter(new String[]{"Data 1", "Data 2", "Data 3"});recyclerView.setAdapter(adapter);}
}

这段代码设置了一个简单的RecyclerView,它使用线性布局显示一个字符串数组中的数据。

总结

RecyclerView是展示集合数据的强大工具,它的灵活性和扩展性使得创建复杂的列表和网格布局变得容易。通过自定义AdapterViewHolder,你可以高度定制每个列表项的展示方式,包括布局和动画效果。此外,RecyclerView还支持添加分隔符、处理点击事件等高级功能。

Fragment的使用和与Activity的交互

Fragment 的基本使用

Fragment是一种可以在Activity内部使用的可复用组件,它有自己的生命周期、接收输入事件,并且可以添加到Activity布局中。Fragment使得在一个Activity中组合多个组件以及在多个Activity之间复用同一个组件成为可能。

创建 Fragment
  1. 定义 Fragment 类:扩展Fragment类,并重写关键的生命周期方法,如onCreateView(),在其中通过布局填充器加载Fragment的布局。

public class ExampleFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_example, container, false);}
}

Fragment 布局:为Fragment创建一个XML布局文件,例如fragment_example.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:text="Hello from the Fragment"/>

在 Activity 布局中声明:在Activity的布局文件中,使用<fragment>标签声明Fragment,或者在Activity的代码中动态添加。

静态添加

<fragment android:name="com.example.ExampleFragment"android:id="@+id/example_fragment"android:layout_width="match_parent"android:layout_height="match_parent" />

动态添加

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

与 Activity 的交互

FragmentActivity的交互通常通过以下几种方式实现:

  1. 通过 Activity 传递数据给 Fragment

    • 可以在创建Fragment的实例时通过Bundle设置参数。
ExampleFragment fragment = new ExampleFragment();
Bundle args = new Bundle();
args.putInt("someInt", 123);
fragment.setArguments(args);

Fragment 回调到 Activity

  • 定义一个回调接口,并让Activity实现它。然后在Fragment内调用Activity的回调方法。
public class ExampleFragment extends Fragment {CallbackInterface callback;@Overridepublic void onAttach(Context context) {super.onAttach(context);try {callback = (CallbackInterface) context;} catch (ClassCastException e) {throw new ClassCastException(context.toString()+ " must implement CallbackInterface");}}public interface CallbackInterface {void onSomeEvent();}
}

然后在Activity中实现这个接口:

public class MainActivity extends AppCompatActivity implements ExampleFragment.CallbackInterface {@Overridepublic void onSomeEvent() {// 处理回调事件}
}

使用 ViewModel

  • ViewModel可以用于Activity和所有的Fragment之间共享数据。它遵循观察者模式,当数据变化时通知UI进行更新。
public class SharedViewModel extends ViewModel {private final MutableLiveData<Integer> selected = new MutableLiveData<Integer>();public void select(int item) {selected.setValue(item);}public LiveData<Integer> getSelected() {return selected;}
}

 然后ActivityFragment都可以观察这个ViewModel中的数据变化。

总结

Fragment为创建动态和可复用的UI组件提供了极大的灵活性。通过合理使用Fragment,你可以使你的应用更加模块化,更容易适应不同的屏幕尺寸和方向。与Activity的交互使得组件之间的数据传递和事件处理成为可能,ViewModel的使用进一步简化了这种交互,使数据管理变得更加高效和简单。

网络编程

学习如何使用HttpURLConnection或OkHttp进行网络请求

在Android开发中,进行网络请求是一项常见需求。HttpURLConnectionOkHttp是两种流行的方式来执行这些请求。下面分别介绍如何使用这两种方法。

使用 HttpURLConnection

HttpURLConnection是Java标准库的一部分,可以直接在Android项目中使用。它支持基本的GET、POST等HTTP方法。

示例:使用HttpURLConnection发起GET请求
new Thread(new Runnable() {@Overridepublic void run() {HttpURLConnection urlConnection = null;try {URL url = new URL("http://www.example.com");urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");InputStream in = new BufferedInputStream(urlConnection.getInputStream());String response = readStream(in);// 处理响应...} catch (Exception e) {e.printStackTrace();} finally {if (urlConnection != null) {urlConnection.disconnect();}}}
}).start();

这个例子展示了如何在一个新线程中发起一个简单的GET请求,并读取响应。注意网络请求必须在非UI线程中执行。

使用 OkHttp

OkHttp是一个第三方库,由Square开发,相比HttpURLConnection,它提供了更简洁的API、更快的速度和更丰富的功能,如连接池、GZIP压缩和请求缓存等。

首先,添加OkHttp的依赖到你的build.gradle文件:

dependencies {implementation 'com.squareup.okhttp3:okhttp:4.9.0'
}

示例:使用OkHttp发起GET请求

OkHttpClient client = new OkHttpClient();String run(String url) throws IOException {Request request = new Request.Builder().url(url).build();try (Response response = client.newCall(request).execute()) {return response.body().string();}
}new Thread(new Runnable() {@Overridepublic void run() {try {String response = run("http://www.example.com");// 处理响应...} catch (IOException e) {e.printStackTrace();}}
}).start();

这个例子展示了如何使用OkHttp发起一个GET请求,并同样需要在非UI线程中执行。

异步请求

对于OkHttp,进行异步请求和处理响应更为方便,只需要使用enqueue方法而不是execute,并提供一个Callback

OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("http://www.example.com").build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);// 处理响应...}
});

这样就不需要手动创建新线程,OkHttp会自动异步执行请求,并在回调中返回结果。

总结

HttpURLConnection是一个基本的网络请求工具,直接内置于Java中,适合简单的网络操作和对第三方库依赖要求较低的场景。而OkHttp提供了更强大的功能和更好的性能,适合需要复杂网络操作、性能优化和更好体验的应用。选择哪一个,取决于你的具体需求和偏好。在实际开发中,由于OkHttp的强大和易用性,它通常是更受欢迎的选择。

理解JSON数据格式,使用Gson或Jackson解析JSON数据

理解 JSON 数据格式

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的对象字面量规范,但独立于语言,因此许多编程语言都有JSON数据格式的解析和生成支持。JSON格式在网络传输数据时特别有用,如API请求的响应通常就是JSON格式。

一个简单的JSON对象例子:

{"name": "John Doe","age": 30,"isStudent": false,"courses": ["Math", "Science"],"address": {"street": "123 Main St","city": "Anytown"}
}

使用 Gson 解析 JSON

Gson是Google提供的用于Java对象和JSON数据之间转换的一个库。它能够将一个JSON字符串转换成等价的Java对象,或者将Java对象转换成其JSON表示形式。

添加 Gson 依赖

首先,在build.gradle文件中添加Gson的依赖:

dependencies {implementation 'com.google.code.gson:gson:2.8.6'
}
解析 JSON 示例

假设有一个JSON表示的用户信息,我们想要将其解析为一个Java对象。

定义一个Java类来表示用户:

public class User {private String name;private int age;private boolean isStudent;private List<String> courses;private Address address;// Address类public static class Address {private String street;private String city;// getters 和 setters}// getters 和 setters
}

使用Gson来解析JSON字符串:

String json = "{...}"; // JSON数据
Gson gson = new Gson();
User user = gson.fromJson(json, User.class);

使用 Jackson 解析 JSON

Jackson是另一个流行的Java库,用于处理JSON。与Gson类似,它也可以轻松地将JSON字符串转换为Java对象,或将Java对象序列化为JSON字符串。

添加 Jackson 依赖
dependencies {implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.3'
}
解析 JSON 示例

使用Jackson解析同样的JSON数据:

String json = "{...}"; // JSON数据
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(json, User.class);

JSON 解析库选择

Gson和Jackson都是处理JSON数据的优秀库,它们提供了丰富的API和灵活的配置。选择哪个主要取决于个人偏好以及特定项目的需求。Gson通常使用起来更简单一些,而Jackson在处理复杂的JSON结构时提供了更多的功能和更高的性能。无论选择哪个,它们都大大简化了JSON数据的处理过程。

数据存储

学习SharedPreferences的使用,用于保存轻量级的本地数据

SharedPreferences是Android平台上一个轻量级的存储方案,主要用于保存应用的配置数据或者是少量的数据需要持久化,比如用户设置、应用内的简单状态等。SharedPreferences以键值对(Key-Value)的形式存储数据,支持基本的数据类型,如booleanfloatintlongString及它们的集合。

使用SharedPreferences存储数据

要使用SharedPreferences存储数据,可以通过ContextgetSharedPreferences方法获取SharedPreferences的实例。这个方法需要两个参数:首先是文件名(如果文件不存在,Android会创建一个),其次是操作模式(通常是MODE_PRIVATE,表示只有当前的应用可以访问这个文件)。

示例:保存数据
SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();editor.putString("key_name", "John Doe");
editor.putInt("key_age", 30);
editor.putBoolean("key_is_student", false);editor.apply(); // 或者 editor.commit();
  • getSharedPreferences方法用于获取一个SharedPreferences实例。
  • 使用edit()方法获得SharedPreferences.Editor对象,然后通过这个对象添加或修改键值对。
  • 调用apply()commit()提交更改。apply()是异步的,没有返回值,而commit()是同步的,会返回一个布尔值表示操作是否成功。

使用SharedPreferences读取数据

要从SharedPreferences读取数据,可以使用相应的get方法,如getStringgetInt等。如果键不存在,可以为这些方法提供一个默认值。

示例:读取数据
SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", MODE_PRIVATE);String name = sharedPreferences.getString("key_name", "No Name");
int age = sharedPreferences.getInt("key_age", 0);
boolean isStudent = sharedPreferences.getBoolean("key_is_student", true);

在这个示例中,如果SharedPreferences中不存在对应的键,getString方法将返回"No Name",getInt将返回0,getBoolean将返回true

注意事项

  • SharedPreferences适合存储轻量级的数据,但不适合存储大量数据或复杂的数据结构。
  • 存储和读取操作都是同步进行的,可能会阻塞主线程。因此,如果有大量数据需要读写,建议在子线程中进行操作,尽管apply()方法已经是异步执行的。
  • 使用SharedPreferences时,数据是以明文形式保存的,因此不应该用来存储敏感信息,如用户密码。

SharedPreferences是实现数据持久化的一种简单而有效的方法,特别适合于保存少量的配置信息或状态数据。

学习SQLite数据库的使用,进行数据的增、删、改、查操作

SQLite是一个轻量级的数据库,它存储在单个磁盘文件上。在Android中,SQLite被广泛用于数据持久化需求,支持标准的SQL语法,并提供了一套Java API,使得在Android应用中进行数据库操作变得简单。

创建 SQLite 数据库

在Android中,通常通过扩展SQLiteOpenHelper类来创建数据库和表。这个类提供了onCreate()onUpgrade()两个回调函数,用于数据库的创建和版本管理。

public class DBHelper extends SQLiteOpenHelper {private static final String DATABASE_NAME = "example.db";private static final int DATABASE_VERSION = 1;public DBHelper(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("CREATE TABLE contacts (" +"_id INTEGER PRIMARY KEY," +"name TEXT," +"email TEXT)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("DROP TABLE IF EXISTS contacts");onCreate(db);}
}

插入数据

使用getWritableDatabase()获取SQLiteDatabase对象,然后通过insert()方法或执行SQL语句插入数据。

DBHelper dbHelper = new DBHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();ContentValues values = new ContentValues();
values.put("name", "John Doe");
values.put("email", "john@example.com");long newRowId = db.insert("contacts", null, values);

查询数据

查询数据通常使用query()方法或直接执行SQL查询语句,并通过Cursor遍历查询结果。

SQLiteDatabase db = dbHelper.getReadableDatabase();Cursor cursor = db.query("contacts",   // 表名称new String[] { "_id", "name", "email" }, // 要查询的列null,         // WHERE子句null,      // WHERE子句的参数null,         // GROUP BY子句null,          // HAVING子句null          // ORDER BY子句
);List<String> names = new ArrayList<>();
while(cursor.moveToNext()) {String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));names.add(name);
}
cursor.close();

更新数据

更新数据可以使用update()方法或直接执行SQL语句。

SQLiteDatabase db = dbHelper.getWritableDatabase();ContentValues values = new ContentValues();
values.put("email", "johndoe@example.com");String selection = "name LIKE ?";
String[] selectionArgs = { "John Doe" };int count = db.update("contacts",values,selection,selectionArgs);

删除数据

删除数据可以使用delete()方法或直接执行SQL语句。

SQLiteDatabase db = dbHelper.getWritableDatabase();String selection = "name LIKE ?";
String[] selectionArgs = { "John Doe" };int deletedRows = db.delete("contacts", selection, selectionArgs);

注意事项

  • 执行数据库操作(尤其是写入和更新操作)时,建议使用事务来保证数据的一致性。
  • 执行完数据库操作后,记得关闭CursorSQLiteDatabase对象,以释放资源。
  • 对于复杂的数据库操作和管理,可以考虑使用Room Persistence Library,它是一个在SQLite之上的抽象层,提供了更简洁的API和编译时的SQL检查。

使用SQLite数据库,可以在Android应用中有效地进行数据持久化操作,对于需要存储大量结构化数据的应用尤其有用。

Android的异步处理

理解并使用AsyncTask和Handler进行异步任务处理

在Android开发中,异步任务处理是常见需求,主要用于执行耗时操作(如网络请求、数据库操作等),而不阻塞主线程(UI线程)。AsyncTaskHandler是实现这一目标的两种常用方法。

AsyncTask

AsyncTask是一个抽象的泛型类,它允许你在后台线程上执行长时间运行的操作,并在完成后将结果发布到UI线程。不过,从Android 11(API级别30)开始,AsyncTask已被标记为过时(deprecated),建议使用其他现代化的方式,如java.util.concurrent或Kotlin 协程。

使用AsyncTask的基本步骤
  1. 定义一个继承AsyncTask的类:指定输入参数、进度和结果的类型。
  2. 实现doInBackground方法:在这里执行后台任务。
  3. (可选)实现onPreExecuteonPostExecuteonProgressUpdate方法:在UI线程上执行操作,如初始化、更新进度和处理结果。
private static class ExampleAsyncTask extends AsyncTask<Void, Void, String> {@Overrideprotected void onPreExecute() {super.onPreExecute();// 在UI线程执行初始化操作}@Overrideprotected String doInBackground(Void... voids) {// 执行耗时后台任务return "Result";}@Overrideprotected void onPostExecute(String result) {super.onPostExecute(result);// 使用后台任务的结果在UI线程上执行操作}
}

执行AsyncTask

new ExampleAsyncTask().execute();

Handler

Handler是Android中处理线程间通信的另一种方式,它允许你发送和处理MessageRunnable对象与一个MessageQueue关联的线程。Handler常用于在工作线程完成任务后更新UI。

使用Handler的基本步骤
  1. 创建Handler实例:在主线程(通常是在ActivityFragment中)创建Handler实例来处理消息或运行代码。
  2. 在工作线程中使用Handler发送消息或执行Runnable
// 在主线程创建Handler
Handler handler = new Handler(Looper.getMainLooper());// 工作线程执行任务
new Thread(new Runnable() {@Overridepublic void run() {// 执行耗时任务// 任务完成,通知UI线程更新handler.post(new Runnable() {@Overridepublic void run() {// 在UI线程执行操作}});}
}).start();

总结

  • AsyncTask:适用于简单的异步任务,尤其是那些直接与UI相关的。然而,因为AsyncTask已被标记为过时,建议使用更现代的并发解决方案。
  • Handler:适用于复杂的线程间通信和对于UI的定时更新或处理。Handler是处理线程间通信的强大工具,但使用时需要更多的注意事项,特别是与线程和消息循环相关的。

对于现代Android开发,推荐使用java.util.concurrent中的类(如ExecutorThreadPoolExecutor)和Kotlin协程,这些方法提供了更强大、更灵活和更简洁的并发和异步处理能力。

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

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

相关文章

【前端】卡片渐变色阴影效果 旋转动画

【前端】卡片渐变色阴影效果 旋转动画 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Breathing…

【G3D笔记】AI生成式3D算法相关环境安装爬坑笔记

【G3D笔记】AI生成式3D算法相关环境安装爬坑笔记) 1、 RayMarching1.1 error C1189: #error: You need C++17 to compile PyTorch1.2 raymarching安装环境版本测试1.3 host_config.h(231): fatal error C1083: 无法打开包括文件: “crtdefs.h”2、Tiny-Cuda-nn2.1 HTTP/2 stre…

mysql体系结构及主要文件

目录 1.mysql体系结构 2.数据库与数据库实例 3.物理存储结构​编辑 4.mysql主要文件 4.1数据库配置文件 4.2错误日志 4.3表结构定义文件 4.4慢查询日志 4.4.1慢查询相关参数 4.4.2慢查询参数默认值 4.4.3my.cnf中设置慢查询参数 4.4.4slow_query_log参数 4.4.…

Hbase java客户端调优——Connections

1、介绍&#xff1a; 大约一年前&#xff0c;有人要求我为一个时间序列产品调优 HBase 的读写性能。该产品在 AWS i2.4XL 中使用 10 个数据节点&#xff0c;并有 15 个计算节点&#xff0c;其中 10 个用于连续写入&#xff0c;5 个用于读取并运行来自这些数据节点的批处理作业…

面试十 简单工厂、工厂方法、抽象工厂

/*简单工厂 Simple Factory&#xff1a;优点&#xff1a;把对象的创建封装在一个接口函数里面&#xff0c;通过传入不同的标识&#xff0c;返回创建的对象&#xff0c;客户不用自己负责new对象缺点 &#xff1a;提供创建对象实例的接口函数不闭合&#xff0c;不能对修改关闭&am…

Git一点通

1.Git的优势 Git是一个伟大的版本管理工具&#xff0c;比之svn&#xff0c;具有以下优势&#xff1a; 分布式版本控制&#xff1a;Git是一种分布式版本控制系统&#xff0c;每个开发者都拥有自己的完整代码库&#xff0c;不需要依赖网络连接就可以进行版本控制、合并和提交操作…

了解测试用例与测试场景

测试用例和测试场景是综合测试中最常见的两种测试工件。正确获得这两个可交付成果对于产品成功至关重要&#xff0c;因为它可以让软件开发团队和测试人员更高效地工作。然而&#xff0c;在 QA 测试中&#xff0c;测试场景和测试用例之间的差异可能会在转换过程中丢失。 测试用例…

opengl日记10-opengl使用多个纹理示例

文章目录 环境代码CMakeLists.txt文件内容不变。fragmentShaderSource.fsvertexShaderSource.vsmain.cpp 总结 环境 系统&#xff1a;ubuntu20.04opengl版本&#xff1a;4.6glfw版本&#xff1a;3.3glad版本&#xff1a;4.6cmake版本&#xff1a;3.16.3gcc版本&#xff1a;10.…

66、将同图片下的多个不同类别的xml标注文件合并成一个xml标注文件-labelImg格式

基本思想:手中有一套抽烟的数据集是labelimg格式,但是没有人物标注的数据集,因此使用自动化标注脚本将图片过滤一边,进行生成labelimg文件,只含有80类别的人物标注xml,然后使用脚本将生成标注的人物xml和手中有的抽烟xml进行合并,生成一份xml文件 代码 # -*- coding: u…

Linux查看8080端口是否启用

在Linux系统中&#xff0c;您可以使用几种不同的命令来检查8080端口是否被启用或正在被某个进程使用。以下是几种常用的方法&#xff1a; 使用lsof命令&#xff1a; sudo lsof -i :8080如果8080端口被某个进程使用&#xff0c;lsof命令将列出相关信息。如果没有输出&#xff0c…

docker和kubectl客户端安装Linux

一、docker安装 1.配置yum源&#xff08;系统组&#xff09; 2.查看可安装docker的所有版本 yum provides docker3.安装最新版本dockers yum install docker3.1确定版本没问题输入 y 4.验证 docker -v5.开启私有仓库的证书验证&#xff0c;没有创建一个daemon.json sudo vi…

设计模式之工厂方法模式解析

工厂方法模式 1&#xff09;问题 简单工厂模式 当需要引入新产品时&#xff0c;由于静态工厂方法通过所传入参数的不同来创建不同的产品&#xff0c;需要修改工厂类的源代码。 2&#xff09;概述 针对不同的产品提供不同的工厂&#xff0c;系统提供一个与产品等级结构对应…

我的保研材料全部损坏了!这个压缩包文件格式未知或数据已经被损坏不可预料的压缩文件末端

求助各位友友&#xff0c;我的保研材料全部没了&#xff01; 之前为了清理D盘&#xff0c;把之前保研期间准备的几个G的材料全部压缩放在了U盘&#xff0c;但是现在却损坏打不开了&#xff0c;之前为了省事也没有添加过“恢复记录”&#xff01;&#xff01;&#xff01; 先声…

阿赵UE学习笔记——20、角色蓝图和动画蓝图

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的使用。这次来看看角色控制动画相关的东西&#xff0c;主要用到了动画蓝图和角色蓝图。 一、动画蓝图 之前分析过&#xff0c;蓝图对于虚幻引擎来说&#xff0c;是存在于各个系统里面的&#xff0c;相当…

js 替换数组中的部分文字内容

用js 把[ "2024-03-20实时", "2024-03-20日前", "运行日实时", "运行日日前"]中把所有的“运行日”替换成 “2023” 可以使用 JavaScript 的 Array.prototype.map() 方法来遍历数组&#xff0c;并使用 String.prototype.replace() 方…

【0274】从shared init file或local init file加载relation cache(2 - 1)

上一篇: 【0273】深入分析 relcache(relation descriptor cache)初始化第一阶段(1) 【0264】深入分析relcache(relation descriptor cache)缓存初始化第2阶段(2) 1. 前言 本文内容是作为《【0264】深入分析relcache(relation descriptor cache)缓存初始化第2阶段…

智慧公厕:卫生、便捷、安全的新时代厕所变革

在城市快速发展的背景下&#xff0c;公共厕所的建设和管理变得越来越重要。智慧公厕作为厕所变革的一项全新举措&#xff0c;通过建立公共厕所全面感知监测系统&#xff0c;以物联网、互联网、大数据、云计算、自动化控制技术为支撑&#xff0c;实现对公共厕所的智能化管理和运…

FPGA学习_时序约束以及VIVADO时序报告

文章目录 前言时序约束的目的一、时序约束种类1、约束主时钟2、约束衍生时钟3、约束虚拟时钟4、input delay5、output delay6、约束异步时钟组7、约束互斥时钟8、假路径约束9、多周期约束 二、VIVADO时序报告三、从时序的角度看为什么寄存器赋值慢一拍 前言 一边学习一边补充当…

消除 Git diff 中的换行符差异(Linux)

通常编辑器默认使用的换行符是跟随操作系统的&#xff0c;而windows操作系统上修改的代码&#xff0c;其换行符会被转成win的\r\n,在提交代码时会显示大量改动&#xff08;对于sh脚本还会存在无法执行的问题&#xff09;&#xff0c;这时候我们可以通过设置git自动转成unix格式…

容器中的大模型(三)| 利用大语言模型:容器化高效地部署 PDF 解析器实践...

作者&#xff1a;宋文欣&#xff0c;智领云科技联合创始人兼CTO 01 简介 大语言模型&#xff08;LLMs&#xff09;正逐渐成为人工智能领域的一颗璀璨明星&#xff0c;它们的强大之处在于能够理解和生成自然语言&#xff0c;为各种应用提供了无限可能。为了让这些模型更好地服务…