Harmony Ble藍牙App(二)連接與發現服務

Ble藍牙App(二)連接與發現服務

  • 前言
  • 正文
    • 一、BlePeripheral回調
    • 二、連接和斷連
    • 三、連接狀態回調
    • 四、發現服務
    • 五、服務提供者
    • 六、顯示服務
    • 七、源碼

前言

??在上一篇中我們進行掃描設備的處理,本文中進行連接和發現服務的數據處理,運行效果圖如下所示:
在這里插入圖片描述

正文

??現在我們在ScanSlice掃描設備,選中一個設備進入MainAbilitySlice,下面要對選中的設備進行處理,首先我們來做連接。

一、BlePeripheral回調

??在之前我們寫了一個BleCore,這里面是對掃描的封裝,那么對于連接來說我們同樣可以封裝到這里,我們可以在BleCore中寫一個BleDeviceCallback 類,繼承自BlePeripheralCallback, 代碼如下所示:

    private class BleDeviceCallback extends BlePeripheralCallback {/*** 連接狀態改變* @param connectionState 狀態碼*/@Overridepublic void connectionStateChangeEvent(int connectionState) {}/*** 發現服務* @param status 狀態*/@Overridepublic void servicesDiscoveredEvent(int status) {}}

??因為本文要做的事情是連接和發現服務,所以我們就先重寫這兩個方法,注意一點的是,藍牙的操作都是在子線程中進行的,如果我們需要知道當前是否連接,則需要寫一個接口用于回調到MainAbilitySlice中,在core包下新建一個BleCallback接口,代碼如下所示:

public interface BleCallback {/*** 設備的所有信息** @param info 信息*/void deviceInfo(String info);/*** 連接狀態** @param state true or false*/void connectionStateChange(boolean state);/*** 發現服務** @param services 服務列表*/void servicesDiscovered(List<GattService> services);
}

??接口中定義了三個方法,通過注釋我們清晰的知道都是什么作用,這里著重介紹第一個函數,這個函數會顯示設備各個時候的狀態信息,從連接之后的所有動作,如果我們需要保存設備的操作日志的話,可以通過這個來進行處理保存。

然后回到BleCore,聲明變量和設置接口回調的方法:

    private final BleDeviceCallback mBleDeviceCallback;private BleCallback bleCallback;private BlePeripheralDevice mDevice;private boolean mIsConnected;public BleCore(Context context) {...//藍牙設備類mBleDeviceCallback = new BleDeviceCallback();}	public void setBleCallback(BleCallback bleCallback) {this.bleCallback = bleCallback;}private void deviceInfo(String info) {if (bleCallback != null) {bleCallback.deviceInfo(info);}}private void connectState(boolean state) {mIsConnected = state;if (bleCallback != null) {bleCallback.connectionStateChange(state);}}public void setDevice(BlePeripheralDevice device) {mDevice = device;}

這里就是對設備信息和連接做了一個處理,下面我們增加連接和斷連的方法。

二、連接和斷連

在BleCore中增加如下代碼:

    public boolean isConnected() {return mIsConnected;}public void connect() {if (mDevice == null) return;deviceInfo("連接設備...");mDevice.connect(false, mBleDeviceCallback);}public void disconnect() {if (mDevice == null) return;deviceInfo("斷開連接設備...");mDevice.disconnect();}

連接與斷開連接,調用時會觸發connectionStateChangeEvent()方法。

三、連接狀態回調

下面修改這個方法的代碼,如下所示:

        @Overridepublic void connectionStateChangeEvent(int connectionState) {String address = mDevice.getDeviceAddr();if (connectionState == ProfileBase.STATE_CONNECTED) {deviceInfo("連接成功:" + address);connectState(true);} else if (connectionState == ProfileBase.STATE_DISCONNECTED) {deviceInfo("斷開連接成功:" + address);connectState(false);mDevice.close();}}

??在回調中,連接成功和斷開連接都會有一個對應的狀態碼,通過狀態回調到接口函數中,然后回到MainAbilitySlice中使用一下這個回調,首先我們修改一下ability_main.xml中的代碼,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:alignment="center"ohos:background_element="$color:bg_color"ohos:orientation="vertical"><DirectionalLayoutohos:height="50vp"ohos:width="match_parent"ohos:alignment="vertical_center"ohos:background_element="$color:blue"ohos:orientation="horizontal"ohos:start_padding="12vp"><Textohos:height="match_content"ohos:width="match_content"ohos:text="操作設備"ohos:text_color="#FFF"ohos:text_font="HwChinese-medium"ohos:text_size="18fp"ohos:weight="1"/><Textohos:id="$+id:tx_disconnect"ohos:height="match_content"ohos:width="match_content"ohos:end_margin="6vp"ohos:padding="8vp"ohos:text="斷開連接"ohos:text_color="#FFF"ohos:text_size="14fp"/></DirectionalLayout><Textohos:id="$+id:tx_device_info"ohos:height="match_content"ohos:width="match_parent"ohos:text="設備信息"ohos:padding="12vp"ohos:text_size="14fp"/><ListContainerohos:id="$+id:lc_service"ohos:height="match_parent"ohos:width="match_parent"/></DirectionalLayout>

??在XML中只增加了兩個Text,分別用于斷連和顯示設備狀態,下面我們寫Slice之間的跳轉,也就是從ScanSlice跳轉到MainAbilitySlice。首先我們在MainAbility中增加action,代碼如下所示:

public class MainAbility extends Ability {@Overridepublic void onStart(Intent intent) {...// add action for abilityaddActionRoute("action.main", MainAbilitySlice.class.getName());}
}

然后去config.json中增加配置,如下圖所示:

在這里插入圖片描述

然后我們回到ScanSlice中,在Item的點擊事件中添加如下代碼:

        //列表item點擊監聽lcDevice.setItemClickedListener((listContainer, component, position, id) -> {//設置設備bleCore.setDevice(mList.get(position).getDevice());Intent jumpIntent = new Intent();Operation operation = new Intent.OperationBuilder().withAction("action.main").withDeviceId("").withBundleName("com.llw.ble").withAbilityName("com.llw.ble.MainAbility").build();jumpIntent.setOperation(operation);startAbility(jumpIntent);});

??這里跳轉的代碼比較多,跳轉之前設置了設備進去,這種方式也是官方推薦的方式。然后我們修改MainAbility中的代碼,如下所示:

public class MainAbilitySlice extends AbilitySlice implements BleCallback {private static final String TAG = MainAbilitySlice.class.getSimpleName();private Text txDisconnect;private Text txDeviceInfo;private ListContainer lcService;private BleCore bleCore;@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);txDisconnect = (Text) findComponentById(ResourceTable.Id_tx_disconnect);txDeviceInfo = (Text) findComponentById(ResourceTable.Id_tx_device_info);lcService = (ListContainer) findComponentById(ResourceTable.Id_lc_service);bleCore = BleApp.getBleCore();bleCore.setBleCallback(this);//連接設備bleCore.connect();txDisconnect.setClickedListener(component -> {if (bleCore.isConnected()) {bleCore.disconnect();} else {bleCore.connect();}});}@Overridepublic void deviceInfo(String info) {getUITaskDispatcher().asyncDispatch(() -> {LogUtils.LogD(TAG, info);txDeviceInfo.setText(info);});}@Overridepublic void connectionStateChange(boolean state) {getUITaskDispatcher().asyncDispatch(() -> txDisconnect.setText(state ? "斷開連接" : "連接"));}@Overridepublic void servicesDiscovered(List<GattService> services) {}
}

??使用BleCoreconnect()方法進行連接設備,在onStart()方法中進行BleCore的賦值,然后設置Ble的回調,實現BleCallback接口,重寫里面的函數,當連接成功之后會通過回調deviceInfo()得到設備狀態,因為是子線程所以在ui線程中渲染UI。而connectionStateChange()函數,回調連接成功或者失敗,如果成功則為ture,就顯示txDisconnect控件,此時連接成功,點擊這個txDisconnect就會斷開連接,點擊監聽就在onStart()中寫好了,下面我們運行一下看看效果。

在這里插入圖片描述

從這個效果圖來看,我們連接成功之后有狀態,點擊斷開連接也會有狀態改變,那么連接就寫好了。

四、發現服務

??連接寫好了,下面可以寫發現服務了,我們可以在連接成功的處理中進行發現服務,下面我們修改一下BleDeviceCallback中的connectionStateChangeEvent()方法中的代碼,如下圖所示:

在這里插入圖片描述

通過mDevice.discoverServices()進行發現服務的動作,在此之前通過deviceInfo()設置當前的動作狀態,發現服務執行會觸發servicesDiscoveredEvent()回調,在這個回調中我們可以回調到頁面,修改代碼如下所示:

        @Overridepublic void servicesDiscoveredEvent(int status) {if (status == BlePeripheralDevice.OPERATION_SUCC) {deviceInfo("發現" + mDevice.getServices().size() + "服務");if (bleCallback != null) {bleCallback.servicesDiscovered(mDevice.getServices());}}}

??在回調中設置發現服務的個數,然后回調,因為服務是多個的,那么下面我們就需要使用一個列表是裝載服務,之前我們就已經在ability_main.xml中寫好了。

五、服務提供者

??要顯示服務列表數據,首先需要一個提供者,而提供者又需要一個item去渲染數據,下面我們在layout下創建一個item_service.xml,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DependentLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_content"ohos:width="match_parent"ohos:background_element="$color:white"ohos:bottom_margin="2vp"ohos:bottom_padding="8vp"ohos:end_padding="16vp"ohos:start_padding="16vp"ohos:top_padding="8vp"><Textohos:id="$+id:tx_service_name"ohos:height="match_content"ohos:width="match_content"ohos:text="服務"ohos:text_size="16fp"/><Buttonohos:id="$+id:tx_uuid_title"ohos:height="match_content"ohos:width="match_content"ohos:below="$id:tx_service_name"ohos:text="UUID:"ohos:text_color="$color:gray"ohos:text_size="16fp"ohos:top_margin="2vp"/><Buttonohos:id="$+id:tx_uuid"ohos:height="match_content"ohos:width="match_content"ohos:below="$id:tx_service_name"ohos:end_of="$id:tx_uuid_title"ohos:text="UUID"ohos:text_size="16fp"ohos:top_margin="2vp"/><Buttonohos:id="$+id:tx_service_info"ohos:height="match_content"ohos:width="match_content"ohos:below="$id:tx_uuid_title"ohos:text="PRIMARY SERVICE"ohos:text_color="$color:gray"ohos:text_size="16fp"ohos:top_margin="2vp"/></DependentLayout>

下面我們在ble包下新建一個BleUtils類,代碼如下所示:

public class BleUtils {public static final String generic = "-0000-1000-8000-00805F9B34FB";public static String getServiceUUID(UUID uuid) {return "0x" + uuid.toString().substring(4, 8).toUpperCase();}/*** 獲取藍牙服務名稱** @param uuid UUID*/public static String getServiceName(UUID uuid) {String targetUuid = getServiceUUID(uuid);switch (targetUuid) {case "0x1800":return "Generic Access service";case "0x1801":return "Generic Attribute service";case "0x1802":return "Immediate Alert service";case "0x1803":return "Link Loss service";case "0x1804":return "Tx Power service";case "0x1805":return "Current Time service";case "0x1806":return "Reference Time Update service";case "0x1807":return "Next DST Change service";case "0x1808":return "Glucose service";case "0x1809":return "Health Thermometer service";case "0x180A":return "Device Information service";case "0x180D":return "Heart Rate service";case "0x180E":return "Phone Alert Status service";case "0x180F":return "Battery service";case "0x1810":return "Blood Pressure service";case "0x1811":return "Alert Notification service";case "0x1812":return "Human Interface Device service";case "0x1813":return "Scan Parameters service";case "0x1814":return "Running Speed and Cadence service";case "0x1815":return "Automation IO service";case "0x1816":return "Cycling Speed and Cadence service";case "0x1818":return "Cycling Power service";case "0x1819":return "Location and Navigation service";case "0x181A":return "Environmental Sensing service";case "0x181B":return "Body Composition service";case "0x181C":return "User Data service";case "0x181D":return "Weight Scale service";case "0x181E":return "Bond Management service";case "0x181F":return "Continuous Glucose Monitoring service";case "0x1820":return "Internet Protocol Support service";case "0x1821":return "Indoor Positioning service";case "0x1822":return "Pulse Oximeter service";case "0x1823":return "HTTP Proxy service";case "0x1824":return "Transport Discovery service";case "0x1825":return "Object Transfer service";case "0x1826":return "Fitness Machine service";case "0x1827":return "Mesh Provisioning service";case "0x1828":return "Mesh Proxy service";case "0x1829":return "Reconnection Configuration service";case "0x183A":return "Insulin Delivery service";case "0x183B":return "Binary Sensor service";case "0x183C":return "Emergency Configuration service";case "0x183D":return "Authorization Control service";case "0x183E":return "Physical Activity Monitor service";case "0x183F":return "Elapsed Time service";case "0x1840":return "Generic Health Sensor service";case "0x1843":return "Audio Input Control service";case "0x1844":return "Volume Control service";case "0x1845":return "Volume Offset Control service";case "0x1846":return "Coordinated Set Identification service";case "0x1847":return "Device Time service";case "0x1848":return "Media Control service";case "0x1849":return "Generic Media Control service";case "0x184A":return "Constant Tone Extension service";case "0x184B":return "Telephone Bearer service";case "0x184C":return "Generic Telephone Bearer service";case "0x184D":return "Microphone Control service";case "0x184E":return "Audio Stream Control service";case "0x184F":return "Broadcast Audio Scan service";case "0x1850":return " Published Audio Capabilities service";case "0x1851":return "Basic Audio Announcement service";case "0x1852":return "Broadcast Audio Announcement service";case "0x1853":return "Common Audio service";case "0x1854":return "Hearing Access service";case "0x1855":return "Telephony and Media Audio service";case "0x1856":return "Public Broadcast Announcement service";case "0x1857":return "Electronic Shelf Label service";default:return "Unknown Service";}}
}

??這里需要說明一下藍牙的UUID,藍牙UUID(Universally Unique Identifier)是用于唯一標識藍牙設備和服務的一種標識符。它是一個128位長的數字,在藍牙通信中起到唯一標識的作用。藍牙UUID按照標準分為兩種類型:

  1. 16位UUID:這些UUID通常用于藍牙標準定義的一些通用服務和特性。例如,設備名稱服務的UUID是 00001800-0000-1000-8000-00805F9B34FB。

  2. 128位UUID:這些UUID通常用于自定義的服務和特性,以確保全球唯一性。可以自行生成一個128位的UUID作為自定義的服務或特性標識。例如,一個自定義的服務UUID可以是 0000XXXX-0000-1000-8000-00805F9B34FB,其中的 XXXX 部分可以是任意的16進制數字。

在藍牙通信中,設備使用UUID來發布和查找服務以及識別特性。UUID是藍牙設備之間進行通信時的重要標識,確保了設備和服務的唯一性。

那么getServiceName()中的鍵你就知道是什么意思了,0x1800就是16進制數字,而對應的值則是SIG定義的,可以參考這個文檔:Assigned_Numbers.pdf。如果你的值找不到對應的,那說明它不是SIG規范的,你這個服務UUID就是自己公司自定義的。

下面我們寫提供者,在provider包下新建一個ServiceProvider類,代碼如下所示:

public class ServiceProvider extends BaseItemProvider {private final List<GattService> serviceList;private final AbilitySlice slice;public ServiceProvider(List<GattService> list, AbilitySlice slice) {this.serviceList = list;this.slice = slice;}@Overridepublic int getCount() {return serviceList == null ? 0 : serviceList.size();}@Overridepublic Object getItem(int position) {if (serviceList != null && position >= 0 && position < serviceList.size()) {return serviceList.get(position);}return null;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic Component getComponent(int position, Component component, ComponentContainer componentContainer) {final Component cpt;ServiceHolder holder;GattService service = serviceList.get(position);if (component == null) {cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_service, null, false);holder = new ServiceHolder(cpt);//將獲取到的子組件信息綁定到列表項的實例中cpt.setTag(holder);} else {cpt = component;// 從緩存中獲取到列表項實例后,直接使用綁定的子組件信息進行數據填充。holder = (ServiceHolder) cpt.getTag();}holder.txServiceName.setText(BleUtils.getServiceName(service.getUuid()));holder.txUuid.setText(BleUtils.getServiceUUID(service.getUuid()));return cpt;}/*** 用于保存列表項的子組件信息*/public static class ServiceHolder {Text txServiceName;Text txUuid;public ServiceHolder(Component component) {txServiceName = (Text) component.findComponentById(ResourceTable.Id_tx_service_name);txUuid = (Text) component.findComponentById(ResourceTable.Id_tx_uuid);}}
}

這里的代碼就是比較簡單的,就是基本的寫法,下面回到MainAbilitySlice中進行顯示數據。

六、顯示服務

首先聲明變量:

    private final List<GattService> serviceList = new ArrayList<>();private ServiceProvider serviceProvider;

然后實現OnItemClickListener 接口

public class MainAbilitySlice extends AbilitySlice implements BleCallback, ListContainer.ItemClickedListener {

重寫onItemClicked()方法,并且增加了一個showMsg,這個Toast的可定制化做的很多。

    @Overridepublic void onItemClicked(ListContainer listContainer, Component component, int position, long id) {showMsg(serviceList.get(position).getUuid().toString());}private void showMsg(String msg) {ToastDialog toastDialog = new ToastDialog(getContext());toastDialog.setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT);toastDialog.setDuration(2000);toastDialog.setText(msg);toastDialog.setAlignment(LayoutAlignment.CENTER);Text toastText = (Text) toastDialog.getComponent();if (toastText != null) {toastText.setMultipleLine(true);toastText.setTextSize(14, Text.TextSizeType.FP);toastText.setTextColor(Color.WHITE);toastText.setPadding(40, 20, 40, 20);ShapeElement toastBackground = new ShapeElement();toastBackground.setRgbColor(new RgbColor(24, 196, 124));toastBackground.setCornerRadius(60f);toastText.setBackground(toastBackground);}toastDialog.show();}

然后在onStart()方法中初始化服務提供者,代碼如下所示:

    @Overridepublic void onStart(Intent intent) {...serviceProvider = new ServiceProvider(serviceList, this);lcService.setItemProvider(serviceProvider);lcService.setItemClickedListener(this);}

修改servicesDiscovered()方法,代碼如下所示:

    @Overridepublic void servicesDiscovered(List<GattService> services) {getUITaskDispatcher().asyncDispatch(() -> {serviceList.clear();serviceList.addAll(services);serviceProvider.notifyDataChanged();});}

這里的寫法其實和掃描設備哪里如出一轍,下面我們運行一下看看,什么效果。

在這里插入圖片描述

七、源碼

如果對你有所幫助的話,不妨 StarFork,山高水長,后會有期~

源碼地址:HarmonyBle-Java

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164717.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164717.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164717.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql數據庫 18.Mysql SQL優化

SQL優化 一、插入優化 多條插入語句&#xff0c;影響執行效率 優化方案 1、批量插入&#xff1a; 在一條insert語句中多條數據&#xff0c;但是如果數據量過大&#xff0c;也不能完全使用一條語句語句&#xff0c;建議數據量為一次性插入1000條以下的數據 如果數據量多大&…

plantUML學習與實戰

背景 在日常工作或者生活中&#xff0c;使用交互圖來描述想法&#xff0c;往往相對于文字來說&#xff0c;可讀性更高&#xff0c;同時一定程度上可以提高溝通效率&#xff0c;但是苦于&#xff0c;不想對一堆控件拖拖拉拉&#xff0c;本人就是一個很討厭畫圖&#xff0c;但是…

【華為OD題庫-036】跳格子2-java

題目 小明和朋友玩跳格子游戲&#xff0c;有n個連續格子組成的圓圈&#xff0c;每個格子有不同的分數&#xff0c;小朋友可以選擇從任意格子起跳&#xff0c;但是不能跳連續的格子&#xff0c;不能回頭跳&#xff0c;也不能超過一圈:給定一個代表每個格子得分的非負整數數組&am…

Python---把函數的返回值作為另外一個函數的參數

def test1():return 50def test2(num):print(num)# 1. 保存函數test1的返回值 result test1()# 2.將函數返回值所在變量作為參數傳遞到test2函數 test2(result) # 50

數據結構 棧和隊列的應用

在昨天分享了有關棧和隊列的基礎知識和基本操作后&#xff0c;今天來分享一些有關棧和隊列的應用 棧和隊列的應用 刪除字符串中的所有相鄰重復項 #include <iostream> #include <stack> using namespace std; string remove(string S) {stack<char> charS…

MySql表中添加emoji表情

共五處需要修改。 語句執行修改&#xff1a; ALTER TABLE xxxxx CONVERT TO CHARACTER SET utf8mb4;

微型計算機原理MOOC題

一、8254 1.掉坑了&#xff0c;AL傳到端口不意味著一定傳到的是低位&#xff0c;要看控制字D5和D4&#xff0c;10是只寫高位&#xff0c;所以是0A00.。。 2. 3. 4.待解決&#xff1a;

優化C++資源利用:探索高效內存管理技巧

W...Y的主頁 &#x1f60a; 代碼倉庫分享&#x1f495; &#x1f354;前言&#xff1a; 我們之前在C語言中學習過動態內存開辟&#xff0c;使用malloc、calloc與realloc進行開辟&#xff0c;使用free進行堆上內存的釋放。進入C后對于動態內存開辟我們又有了新的內容new與dele…

CCC聯盟——UWB MAC(一)

本文在前面已經介紹了相關UWB的PHY之后&#xff0c;重點介紹數字鑰匙&#xff08;Digital Key&#xff09;中關于MAC層的相關實現規范。由于MAC層相應涉及內容比較多&#xff0c;本文首先從介紹UWB MAC的整體框架&#xff0c;后續陸續介紹相關的網絡、協議等內容。 1、UWB MAC架…

真心的表揚與鼓勵,勝過一萬句說教

今天我想和大家分享一下&#xff0c;怎樣跟孩子運用鼓勵和表揚。我記得魯道夫德雷克斯是阿德勒學派的心理學家&#xff0c;也是來自《孩子的挑戰》一書的作者&#xff0c;他說孩子們需要鼓勵&#xff0c;就像植物需要水&#xff0c;鼓勵能讓孩子知道自己做的事與自己是什么樣的…

非自定義Bean注解開發Bean配置類的注解開發

目錄 非自定義Bean注解開發 Bean配置類的注解開發 非自定義Bean注解開發 非自定義的Bean不能像自定義Bean使用Component進行管理&#xff0c;非自定義Bean要通過工廠的方式進行實例化&#xff0c;使用Bean標注方法即可&#xff0c;Bean的屬性文beanName 如果Bean工廠方法需要參…

[23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution

paper | proj | code 提出一種基于K-Planes的4D point cloud Representation&#xff1b;提出一種Hybrid appearance model&#xff0c;包含image blending model和SH model。其中&#xff0c;image blending model將3D點映射回原圖中求得&#xff0c;SH model通過模型預測求得…

【工具欄】熱部署不生效

目錄 配置熱部署&#xff1a; 解決熱部署不生效&#xff1a; 首先檢查&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a; 配置熱部署&#xff1a; https://blog.csdn.net/m0_67930426/article/details/133690559 解決熱部署不…

Python中的解析器argparse

import argparse## 構造解析器 argparse.ArgumentParser() parse argparse.ArgumentParser(description"caculateing the area of rectangle")## 添加參數 .add_argument() parse.add_argument("--length",typeint,default20,helpThe length of rectangle…

【追求卓越09】算法--散列表(哈希表)

引導 通過前面幾個章節的學習&#xff08;二分查找&#xff0c;跳表&#xff09;&#xff0c;我們發現想要快速查找某一個元素&#xff0c;首先需要將所有元素進行排序&#xff0c;再利用二分法思想進行查找&#xff0c;復雜度是O(logn)。有沒有更快的查找方式呢&#xff1f; 本…

微軟發布最新.NET 8長期支持版本,云計算、AI應用支持再強化

11 月 15 日開始的為期三天的 .NET Conf 在線活動的開幕日上&#xff0c;.NET 8作為微軟的開源跨平臺開發平臺正式發布。.NET 團隊著重強調云、性能、全棧 Blazor、AI 和 .NET MAUI 是.NET 8的主要亮點。.NET團隊在 .NET Conf 2023 [1]活動開幕式上表示&#xff1a;“通過這個版…

nginx 模塊相關配置及結構理解

文章目錄 模塊配置結構模塊配置指令先看一下 ngx_command_t 結構一個模塊配置的demo簡單模塊配置的案例演示 模塊上下文結構模塊的定義 模塊配置結構 Nginx中每個模塊都會提供一些指令&#xff0c;以便于用戶通過配置去控制該模塊的行為。 Nginx的配置信息分成了幾個作用域(sc…

使用注解的AOP編程

使用注解的AOP編程 當注解沒有參數時 當使用注解進行面向切面編程&#xff08;AOP&#xff09;時&#xff0c;你可以按照以下步驟來實現&#xff1a; 步驟&#xff1a; 1. 創建自定義注解&#xff1a; 首先&#xff0c;創建自定義的注解&#xff0c;以便在代碼中標記需要進…

Excel換不了行怎么解決?

方法一: 使用Alt Enter鍵 在Excel中&#xff0c;輸入文字時按下回車鍵&#xff0c;光標將會移到下一個單元格&#xff0c;如果想要換行&#xff0c;可以嘗試使用Alt Enter鍵。具體操作如下: 1.在單元格中輸入文字; 2.想要換行時&#xff0c;在需要換行的位置按下Alt Enter鍵; 3…

延時任務定時發布,基于 Redis 與 DB 實現

目錄 1、什么是延時任務&#xff0c;分別可以使用哪些技術實現&#xff1f; 1.2 使用 Redis 和 DB 相結合的思路圖以及分析 2、實現添加任務、刪除任務、拉取任務 3、實現未來數據的定時更新 4、將數據庫中的任務數據&#xff0c;同步到 Redis 中 1、什么是延時任務&#xff…