Flutter 基礎知識總結

1、Flutter 介紹與環境安裝

為什么選擇 Dart:

  • 基于 JIT 快速開發周期:Flutter 在開發階段采用 JIT 模式,避免每次改動都進行編譯,極大的節省了開發時間
  • 基于 AOT 發布包:Flutter 在發布時可以通過 AOT 生成高效的 ARM 代碼以保證應用性能
  • UI 幀率可達 120 FPS:為了快速流暢的用戶體驗需要能夠在每個動畫幀運行大量的代碼,不能有周期性的停頓,否則會造成掉幀
  • 單線程:不需要鎖,不存在數據競爭和變量狀態同步,也沒有線程上下文切換的性能損耗和鎖導致的卡頓
  • 垃圾回收:多生代(參考了 JVM)無鎖垃圾回收器,專門為 UI 框架中常見的大量 Widgets 對象創建和銷毀優化

JIT(Just In Time)即時編譯,在程序執行期間實時編譯為本地機器碼;AOT(Ahead Of Time)靜態編譯,程序運行前編譯成本地機器碼。在代碼的執行效率上,JIT 不如 AOT。

2、Dart 基礎語法

2024-5-17.Dart基礎一

Dart 不用編譯了,dart xxx.dart 直接就執行,不像 Java 需要先 javac 編譯出 class 文件再 java xxx.class 執行。

2.1 變量

類型與聲明

變量都是引用類型,未初始化的變量的值是 null。

聲明變量的方式通常有三種:

  1. Object:與 Java 一樣 Object 是所有類的基類,Object 聲明的變量可以是任意類型。比如數字(包括 int 類型的數字)、方法和 null 都是對象
  2. var:聲明的變量在賦值的那一刻,決定了它是什么類型
  3. dynamic:不是在編譯時候確定實際類型的,而是在運行時。dynamic 聲明的變量行為與 Object 一樣,使用一樣,關鍵在于運行時原理不同

示例代碼:

void test1() {// 1.通過類型聲明變量Object i = "Test";// 2.通過 var 聲明變量var j = "Test";// 報錯,聲明時已經確定了變量類型,不可更改// j = 100;// 3.聲明時沒有具體指明是什么類型,那么就是默認的 Object 類型var k;// 可以為 k 賦值為 Object 的子類型k = "Test";k = 100;// 4.dynamic 動態類型可以賦值不同類型dynamic z = "Test";z = 100;
}

需要注意的地方:

  • 所有類型,沒有初始化的變量自動獲取一個默認值為 null
  • 聲明變量時,可以選擇加上具體類型,如int a = 1;,但對于局部變量,按照 Dart 代碼風格,使用 var 而不是具體類型

final 與 const

final 聲明運行時常量,const 聲明編譯器常量(相比于運行時常量可讓代碼運行更高效),二者都用于聲明常量,可以替代任何類型,只能在聲明時初始化,且不能改變:

void test2() {// 1.const 與 final 可以替代任何類型const a = 1;final b = 1;const int c = 1;final int d = 1;// 2.不能通過運行時常量構造編譯時常量final m = 1;// 企圖通過運行時常量構造編譯時常量,導致 const 值無法確定// const n = m + 1;// 使用編譯時能夠確定的值構造 const 常量是可以的const x = 1;const y = x + 1;
}

類的變量可以是 final 但不能是 const。如果 const 變量在類中,需要定義為 static const 靜態常量:

class T {static const i = 2; // 正確const j = 1; // 錯誤
}

2.2 內置類型

Dart 內置以下類型:

  • numbers
  • strings
  • booleans
  • lists(也被稱之為 arrays)
  • maps
  • runes(用于在字符串中表示 Unicode 字符)
  • symbols

數值 num

num 是數字類型的父類,有兩個子類 int 和 double。

int 的默認實現是 64 位,如果編譯成 JavaScript,就是 32 位。在編碼時,如果 int 長度超過 4 個字節,那么 Dart 會將其編譯為類似 Java 的 long 類型,否則編譯成 Java 中的 short 或 int。

也就是說,int 的長度是動態確定的,可以通過 int 的 bitLength() 確定存儲該 int 變量所需要的最小的位數。

但實際上,不應該將 Dart 的 int 和 Java 的 int 做類比,因為前者是一個類,后者是一個基本類型的關鍵字。從本質上說,二者不是一個東西,沒有可比性。

字符串 String

Dart 字符串是 UTF-16 編碼的字符序列,使用方法如下:

  • 可以使用單引號或者雙引號來創建字符串:

    var name = 'lance';
    // 如果插入一個簡單的標識符,而后面沒有緊跟更多的字母數字文本,那么 {} 應該被省略
    var a = "my name is $name!";
    var b = "my name is ${name.toUpperCase()}!";
    
  • 與 Java 一樣可以使用 + 操作符來把拼接字符串,也可以把多個字符串放到一起來實現同樣的功能:

    var a  = "my name is " "lance";
    
  • 使用三個單引號或者雙引號可以創建多行字符串對象:

    var s1 = '''
    You can create
    multi-line strings like this one.
    ''';var s2 = """This is also a
    multi-line string.""";
    
  • 可以通過單引號嵌套雙引號,或雙引號嵌套單引號進行轉義:

    print("'Test'"); // 'Test'
    print('"Test"'); // "Test"
    
  • 也可以使用 Java 的方式轉義,或者使用 Dart 的 r 前綴創建一個原始字符串實現轉義:

    // 兩行輸出結果均為 換行符 \n
    print("換行符 \\n");
    print(r"換行符 \n");
    

布爾類型 bool

Dart 的布爾類型 bool 有 true 和 false 兩個對象。

列表 List

Dart 的數組是 List 對象,它有兩種聲明方式:

  1. 當作 List 對象聲明:

    // new 可以省略
    var list = new List(1);
    
  2. 當作數組聲明:

    var list = [1, 2, 3];
    

通過 for 循環遍歷 List 也有兩種方式:

for(var item in list) {print(item);
}for(var j = 0;j < list.length; ++j) {print(list[j]);
}

當數組與 const 相結合時,需要注意:

	List<int> list1 = const[1,2,3];// Unsupported operation: Cannot add to an unmodifiable list//list1.add(4);const List<int> list2 = [1,2];// Error: Can't assign to the const variable 'list2'.//list2 = list1;// Unsupported operation: Cannot add to an unmodifiable list//list2.add(4);

const 修是誰,誰就不可變:

  • list1 指向不可變的 [1,2,3],那么就不能修改數組,但是可以指向其他數組對象
  • list2 本身是一個常量引用,那么它就只能指向 [1,2],不能修改索引,也不能修改索引的內容

映射集合 Map

兩種聲明方式:

var companys = {'a': '阿里巴巴', 't': '騰訊', 'b': '百度'};
var companys2 = new Map();
// 添加元素
companys2['a'] = '阿里巴巴';
companys2['t'] = '騰訊';
companys2['b'] = '百度';// 獲取與修改元素
var c = companys['c']; // 沒有對應的 key 返回null
companys['a'] = 'alibaba'; 

const 與 Map 結合的情況與 List 樣。

Runes

Runes 主要用于獲取特殊字符的 Unicode 編碼,或者需要將 32 位的 Unicode 編碼轉換為字符串。

Dart 表達 Unicode 代碼點的常用方法是 \uXXXX,其中 XXXX 是 4 位十六進制值。要指定多于或少于 4 個十六進制數字,需要將值放在大括號中:

var clapping = '\u{1f44f}'; // 5 個 16 進制 需要使用 {}
print(clapping); //👏
// 獲得 16 位代碼單元
print(clapping.codeUnits); // [55357, 56399]
// 獲得 Unicode 代碼
print(clapping.runes.toList()); // [128079]// fromCharCode 根據字符碼創建字符串
print(String.fromCharCode(128079));
print(String.fromCharCodes(clapping.runes));
print(String.fromCharCodes([55357, 56399]));
print(String.fromCharCode(0x1f44f));Runes input = new Runes('\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(String.fromCharCodes(input));

這里要清楚一個代碼點和代碼單元的概念:

代碼點(Code Point)和代碼單元(Code Unit)

代碼單元與代碼點

簡言之,代碼點就是字符集中每個字符的值,比如上面代碼中👏符號在 Unicode32 中的值為 0x1f44f。

代碼單元指編碼集中具有最短比特組合的單元。對于 UTF-8 來說,代碼單元是 8 比特長;對于 UTF-16 來說,代碼單元是 16 比特長。換一種說法就是 UTF-8 的是以一個字節為最小單位的,UTF-16 是以兩個字節為最小單位的。

我們在 Java 中常說 String.length() 是獲取字符串長度,實際上是不嚴謹的,應該說是 UTF-16 編碼表示下的代碼單元數量,而不是字符個數。例如:

String a = "\uD83D\uDC4F";
printf(a); // 👏
printf(a.length()); // 2

你看打印輸出的長度為代碼單元個數 2,而不是 a 中字符的個數。charAt() 也是類似的情況。

Symbols

操作符標識符,可以看作C中的宏。表示編譯時的一個常量:

var i = #A; // 常量
print(i.runtimeType); // Symbolmain() {print(i);switch(i) {case #A:print("A");break;case #B:print("B");break;}var b = new Symbol("b");print(#b == b); // true
}

2.3 操作符

主要看 Java 沒有的操作符:

  1. 類型判定操作符:is!is 用于判斷對象是否為某種類型,as 用于將對象轉換為特定類型

  2. 賦值操作符:??= 用來指定值為 null 的變量的值,比如:

    // 如果 b 是 null,則 value 賦值給 b,否則 b 的值保持不變
    b ??= value;
    
  3. 條件表達式:

    • condition ? expr1 : expr2:如果 condition 為 true 則執行 expr1,否則執行 expr2
    • expr1 ?? expr2:如果 expr1 不為 null 則取 expr1,否則返回 expr2 的值
  4. 級聯操作符:..可以在同一個對象上連續調用多個函數以及訪問成員變量,這樣可以避免創建臨時變量,代碼看起來也更加流暢:

    // StringBuffer write() 相當于 Java 的 append
    var sb = new StringBuffer();
    sb..write('foo')..write('bar');
    
  5. 安全操作符:?.左值如果為 null 則返回 null:

    String sb;
    // 報空指針異常
    print(sb.length);
    // 打印輸出 null
    print(sb?.length);
    

3、方法

3.1 一等方法對象

Dart 是一個真正的面向對象語言,方法也是對象,類型為Function。 這意味著,方法可以賦值給變量,也可以當做其他方法的參數。可以把方法當做參數調用另外一個方法。

在 Java 中如果需要能夠通知調用者或者其他地方方法執行過程的各種情況,可能需要指定一個接口,比如 View 的 OnClickListener。而在 Dart 中,我們可以直接指定一個回調方法給調用的方法,由調用的方法在合適的時機執行這個回調:

void setListener(Function listener) {listener("Success");
}// 或者
void setListener(void listener(String result)){listener("Success");
}// 兩種方式,第一種調用者根本不確定回調函數的返回值、參數是些什么
// 第二種則需要寫這么一大段,太麻煩// 第三種:類型定義,將返回值為 void,參數為一個 String 的方法定義為一個類型
typedef void Listener(String result)void setListener(Listener listener){listener("Success");
}

上面演示了方法作為參數的三種形式:

  1. 第一種使用 Function 表示一個方法,但是這種形式無法確定方法的參數以及返回值類型,因此不好
  2. 第二種直接將方法的原型寫在方法參數中,寫起來麻煩,看起來也不舒服,因此也 pass
  3. 第三種將方法定義為一個類型,使用該類型作為方法參數,推薦這種寫法

3.2 可選命名參數

將方法的參數放到 {} 中就變成可選命名參數:

int add({int? i, int? j}) {if (i == null || j == null) {return 0;}return i + j;
}

調用方法時使用 key-value 形式指定參數:

void main() {print(add()); // 0print(add(i: 1, j: 2)); // 3
}

3.3 可選位置參數

將方法的參數放到 [] 中就變成可選位置參數,傳值時按照參數位置順序傳遞:

int add([int? i, int? j]) {if (i == null || j == null) {return 0;}return i + j;
}

調用時可以不傳入全部的參數,參數按照參數聲明的順序賦值:

void main() {print(add()); // 0print(add(1)); // 0print(add(1, 2)); // 3
}

可選命名參數與可選位置參數的出現使得方法重載的實現更容易。在 Java 中,方法重載需要寫出多個不同參數的方法,但是在 Dart 中通過將方法聲明為可選命名參數或可選位置參數,寫一個方法,在調用時傳入所需參數即可。

3.4 默認參數值

定義方法時,可選參數可以使用 = 來定義可選參數默認值:

int add([int i = 1, int j = 2]) => i + j;
int add({int i = 1, int j = 2}) => i + j;

3.5 匿名方法

沒有名字的方法,稱之為匿名方法,也可以稱之為 lambda 或者 closure 閉包。匿名方法的聲明方式為:

([Type] param1,) { codeBlock; 
}; 

比如:

var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
list.forEach((i) {print(i);
});

4、異常

Dart 的異常機制也像 Kotlin 一樣非常靈活,不像 Java 那樣強制你捕獲異常。

所有的 Dart 異常是非檢查異常,方法不一定聲明了他們所拋出的異常, 并且不要求你捕獲任何異常。

Dart 的異常類型有ExceptionError兩種根類型還有若干個它們的子類型,在拋出異常時,可以拋出任何非 null 對象,不局限于ExceptionError以及它們的子類型:

throw new Exception('這是一個異常');
throw '這是一個異常';
throw 123;

Dart 雖然也支持 try-catch-finally 捕獲異常,但是 catch 無法指定類型,需要結合 on 使用:

try {throw 123;
} on int catch(e) {// 使用 on 指定捕獲 int 類型的異常對象,on TYPE catch(e)      
} catch(e,s) { // 兩個參數的類型分別為 _Exception 和 _StackTracerethrow; // 使用 `rethrow` 關鍵字可以把捕獲的異常給重新拋出
} finally {}

catch() 可以接收兩個參數:

  • 第一個參數 e 是被拋出的異常對象,類型是 _Exception
  • 第二個參數 s 是堆棧信息對象,類型是 _StackTrace,通過 print(s) 可以輸出異常堆棧信息

騷操作,拋出異常時拋出一個方法,catch 的時候可以通過捕獲 Function 類型來執行該方法。

5、類

Dart 是面向對象的語言,所有類都繼承自 Object。

命名風格:

  • 使用 lowercase_with_underscores 風格命名庫和文件名
  • 使用 upperCamelCase 命名類型名稱
  • 使用 lowerCamelCase 命名其他標識符
  • 推薦使用 lowerCamelCase 命名常量

每個實例變量會自動生成一個隱含的 getter 方法,非 final 實例變量還會自動生成一個 setter 方法:

class Point {// 公有變量num x = 0;// _開頭的是私有變量num _y = 0;
}

Dart 在作用域上并沒有 Java 那樣 public、private 的關鍵字,作用域只有公有與私有之分,用 _ 開頭表示私有變量或私有類,不以 _ 開頭的就是公有的類或變量。

5.1 構造函數

常規構造函數

class User {// 初始值一定要給,否則編譯不通過String name = "";int age = 0;User(String name, int age) {this.name = name;this.age = age;}
}

由于把構造函數的參數賦值給實例變量的場景太常見,因此 Dart 提供了語法糖來簡化操作:

class User {String name = "";int age = 0;User(this.name, this.age);
}

也可以使用 {} 將構造函數的參數聲明為可選位置參數,只不過此時不能用 this:

class User {// 成員變量要有初始值String name = "";int age = 0;// 使用可選命名參數,由于 name 和 age 都不可為 null,因此// 參數也需要設置默認值,防止沒有為其傳參時將成員變量賦值為 nullUser({String name = "", int age = 0}) {this.name = name;this.age = age;}
}void main() {var user0 = User(name: "User0"); // name = User0, age = 0var user1 = User(age: 30); // name = , age = 30var user2 = User(age: 22, name: "User2"); // name = User2, age = 22
}

命名構造函數

Dart 不允許任何函數的重載,不論是構造函數還是成員函數還是頂級函數。但有時我們確實有重載構造函數的需求,此時可以使用命名構造函數為一個類實現多個構造函數:

class User {String name = "";int age = 0;User(this.name, this.age);// 命名構造函數,在 . 后面隨意取名,調用時也使用改名字進行構造即可User.fromJson(Map json) {name = json['name'];age = json['age'];}
}void main() {var map = {'name': 'User', 'age': 33};var user = User.fromJson(map);
}

好處是可以通過名字判斷出構造函數的大致意圖和內容,更加直觀。比如 User.fromJson() 就能看出是通過 Json 數據構造 User 對象。

構造函數初始化列表

這一點跟 C++ 很像:

class User {String name = "";int age = 0;User(String name, int age): name = name,age = age;User.fromJson(Map json): name = json['name'],age = json['age'];
}

重定向構造函數

class View {View(int context, int attr);// 會調用上面的構造函數View.a(int context) : this(context, 0);
}

常量構造函數

這里的常量指的是編譯器常量,首先需要使用 const 修飾構造函數:

class ImmutablePoint {final int x;final int y;// 常量構造函數要求成員必須是 final 的const ImmutablePoint(this.x, this.y);
}

然后在構造對象時,不使用 new,而是使用 const,并且要求構造不同對象時傳入的參數必須是一樣的:

void main() {var p1 = const ImmutablePoint(1, 1);var p2 = const ImmutablePoint(1, 1);var p3 = const ImmutablePoint(1, 2);var p4 = new ImmutablePoint(1, 1);print('''p1 == p2:${p1 == p2}
p1 == p3:${p1 == p3}
p1 == p4:${p1 == p4}''');
}

輸出結果為:

p1 == p2:true
p1 == p3:false
p1 == p4:false

主要用于同一個對象被多次使用時,比如 UI 上顯示三個相同的 ListItem,使用常量構造函數就可以創建出一個對象,而不是三個對象,節省了內存。

工廠構造函數

使用 factory 關鍵字修飾,必須返回一個本類或子類的實例對象:

class Person {// 返回本類對象factory Person.get() {return new Person();}// 返回子類對象factory Person.getStudent() {return new Student();}// 如果想要被,需要有一個常規構造函數Person();
}class Student extends Person {}

在 Dart 中使用單例模式時就可以用到 factory:

class Person {// 使用 _ 讓靜態對象私有化,并且類型后面加問號表示為可空// 類型,否則就要在聲明 Person 對象時立即為其初始化static Person? _instance;// 定義工廠構造函數返回單例factory Person.getInstance() {// 如果 _instance 為 null 才創建對象_instance ??= Person._newInstance();// 返回 _instance,后接的感嘆號表示非 null return _instance!;}// 創建一個私有的常規構造函數,這樣默認的構造函數 Person() 就沒有了 Person._newInstance();
}

這樣在 Person 類所在的文件之外,就無法訪問到私有的 _instance 和 _newInstance(),只能通過 getInstance() 獲取到 Person 的單例:

var person = Person.getInstance();

5.2 getter & setter

Dart 中每一個實例屬性都會有一個隱式的 getter,非 final 還有 setter。

首先來看一個錯誤示例:

class Point {int x = 0;int get x => x + 10;
}

在定義 x 的 getter 時編譯器會報錯,說 x 已經定義過。因此如果想自定義屬性的 getter 或 setter 需要將屬性聲明為私有的:

class Point {int _x = 0;int _y = 0;int get x => _x + 10;int get y => _y + 20;
}

在一個需要注意,getter 與 setter 是方法,而不是屬性,因此可以在方法名后面加上 {} 在里面寫相關邏輯:

class Point {int _x = 0;int get x {return _x + 10;}// setter 需要有一個參數set x(int value) {_x = value;}
}

5.3 操作符重載

重載 + 運算符:

class Point {int x = 0;int y = 0;Point(this.x, this.y);// 用 operator 接上要重載的操作符Point operator +(Point other) => Point(x + other.x, y + other.y);
}

這樣可以用 + 連接兩個 Point 對象:

void main() {var point = Point(10, 20) + Point(30, 50);print("x = ${point.x}, y = ${point.y}"); // x = 40, y = 70
}

Dart 的操作符重載非常靈活,返回值的類型不受限制,比如上面重載 + 時返回一個 Point 是我們的常規操作,但是你也可以根據自己需要返回其他類型,比如 String、int 等等。

5.4 抽象類與接口

使用 abstract 定義抽象類,抽象類中允許出現無方法體的方法:

abstract class Parent {String name = "";// 抽象方法前面不能加 abstractvoid printName();
}

Dart 沒有 interface 關鍵字,Dart 中的每個類都隱式定義了一個包含所有實例成員的接口:

class A {void a() {}
}class B implements A {void a() {}
}

5.5 其他語法

可調用的類

如果類中定義了 call 方法,可以通過該類實例對象后接 () 的形式快速調用 call:

void main() {var a = A();a();
}class A {void call() {print("invoke call method.");}
}

call 方法可以帶參數。

混合 mixins

mixins 是一種在多類繼承中重用一個類代碼的方法,基本形式如下:

void main() {var c = C();c.a();c.b();c.c();
}mixin A {void a() {}
}mixin B {void b() {print("B");}
}class C with A, B {void c() {}void b() {print("C");}
}

注意:

  • 被混入的類需要用 mixin 聲明,并且不能有構造函數,否則就無法作為被混入的類出現在 with 后面

  • 混合結果的 C 類中,可以重寫,也可以重新定義 A、B 中的方法

  • 如果 A、B 內定義了同名方法,且 C 也定義了同名方法,那么 C 的實例在調用該方法時實際上調用的是 C 中的方法;如果 C 中沒有定義同名方法,那么 C 調用的就是 B 中的方法(根據 with 后面的排序,優先取順位靠后的)

  • 在 C 中可以通過 super 調用 A 或 B 中的方法,比如:

    mixin A {void a() {}
    }class C with A, B {void a() {super.a();}
    }
    
  • 上述幾點能發現 mixin 與多繼承的表現有很多相似之處

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

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

相關文章

Jenkins 持續集成部署

Jenkins的安裝與部署 前言 當我們在實施一個項目時&#xff0c;從新代碼中獲得反饋的速度越快&#xff0c;問題越早得到解決&#xff0c;獲得反饋的一種常見方法是在新代碼之后運行測試&#xff0c;但這就導致了當代碼正在編譯并且正在運行測試時&#xff0c;開發人員無法在測…

跨站請求偽造之基本介紹

一.基本概念 1.定義 跨站請求偽造&#xff08;Cross - Site Request Forgery&#xff0c;縮寫為 CSRF&#xff09;漏洞是一種網絡安全漏洞。它是指攻擊者通過誘導用戶訪問一個惡意網站&#xff0c;利用用戶在被信任網站&#xff08;如銀行網站、社交網站等&#xff09;的登錄狀…

Pytorch | 利用BIM/I-FGSM針對CIFAR10上的ResNet分類器進行對抗攻擊

Pytorch | 利用BIM/I-FGSM針對CIFAR10上的ResNet分類器進行對抗攻擊 CIFAR數據集BIM介紹基本原理算法流程 BIM代碼實現BIM算法實現攻擊效果 代碼匯總bim.pytrain.pyadvtest.py 之前已經針對CIFAR10訓練了多種分類器&#xff1a; Pytorch | 從零構建AlexNet對CIFAR10進行分類 Py…

如何更好的進行時間管理

先想一下我們想要做的事情&#xff0c;然后拿出Excel表格將這些事情記錄下來&#xff0c;我們把它叫做任務對這些任務按照重要性&#xff0c;緊急程度進行排序&#xff0c;拿出表格中的前六個任務&#xff0c;就是今天要做的任務新建另一張excel表格&#xff0c;表格的一列為時…

OpenGL —— 2.6.1、繪制一個正方體并貼圖渲染顏色(附源碼,glfw+glad)

源碼效果 C++源碼 紋理圖片 需下載stb_image.h這個解碼圖片的庫,該庫只有一個頭文件。 具體代碼: vertexShader.glsl #version

ubuntu開機進入initramfs狀態

虛擬機卡死成功起后進入了initramfs狀態&#xff0c;可能是跟文件系統有問題或者檢索不到根文件系統&#xff0c;或者是配置錯誤&#xff0c;系統磁盤等硬件問題導致 開機后進入如下圖的界面&#xff0c; 文中有一條提示 要手動fsck 命令修復 /dev/sda1 命令如下 fsck /de…

java根據Word模板實現動態填充導出

最近項目中需要導出Word&#xff0c;根據不同的信息導出不同的內容&#xff0c;包含文本、列表、圖片等&#xff0c;本文使用poi-tl實現在次做以記錄。 添加依賴 <!-- word導出 --> <dependency><groupId>com.deepoove</groupId><artifactId>po…

mindie推理大語言模型問題及解決方法匯總

問題說明 使用功能mindie 1.0 RC2推理大語言模型&#xff0c;遇到不少問題&#xff0c;記錄下解決思路。 我的硬件是910B4。 問題及解決 問題1 在docker內啟動mindie時終端報錯 Fatal Python error: PyThreadState_Get: the function must be called with the GIL held, …

Selenium 全面指南

Selenium 是一個強大的 Web 自動化工具&#xff0c;支持多種瀏覽器和語言綁定。 1. Selenium 的基本概念 WebDriver&#xff1a;Selenium 提供的核心接口&#xff0c;用于控制瀏覽器操作。顯式等待&#xff1a;等待特定條件滿足后再執行操作。隱式等待&#xff1a;全局設置一個…

Go框架比較:goframe、beego、iris和gin

由于工作需要&#xff0c;這些年來也接觸了不少的開發框架&#xff0c;Golang的開發框架比較多&#xff0c;不過基本都是Web"框架"為主。這里稍微打了個引號&#xff0c;因為大部分"框架"從設計和功能定位上來講&#xff0c;充其量都只能算是一個組件&…

【華為OD-E卷-木板 100分(python、java、c++、js、c)】

【華為OD-E卷-木板 100分&#xff08;python、java、c、js、c&#xff09;】 題目 小明有 n 塊木板&#xff0c;第 i ( 1 ≤ i ≤ n ) 塊木板長度為 ai。 小明買了一塊長度為 m 的木料&#xff0c;這塊木料可以切割成任意塊&#xff0c;拼接到已有的木板上&#xff0c;用來加…

sqlserver臨時表來做表聯查復雜查詢

使用臨時表&#xff0c;先查詢出結果&#xff0c;在用于后面表的子查詢或者聯查 -- 刪除表1if EXISTS ( SELECT 1 FROM tempdb.sys.objects where name like #temp_PublishRecord% ) beginDROP TABLE #temp_PublishRecordprint 已刪除臨時表 #temp_PublishRecordend--創…

OMG DDS 規范漫談:分布式數據交互的演進之路

一、由來與起源脈絡 OMG DDS&#xff08;Object Management Group Data Distribution Service&#xff09;的發展是計算機科學和技術進步的一個縮影&#xff0c;它反映了對高效、可靠的數據共享需求的響應。DDS 的概念萌生于20世紀90年代末&#xff0c;當時分布式計算已經從理…

1.使用 Couchbase 數倉和 Temporal(一個分布式任務調度和編排框架)實現每 5 分鐘的增量任務

在使用 Couchbase 數倉和 Temporal&#xff08;一個分布式任務調度和編排框架&#xff09;實現每 5 分鐘的增量任務時&#xff0c;可以按照以下步驟實現&#xff0c;同時需要注意關鍵點。 實現方案 1. 數據層設計&#xff08;Couchbase 增量存儲與標記&#xff09; 在 Couchb…

Spring源碼分析之AOP-@EnableAspectJAutoProxy

前言 這篇文章之前我們說了Springboot的啟動流程,Bean對象怎么實現從無到有的一個過程還有一些接口的拓展的實現等等那么從這一篇文章開始的話我們就會開始說一說我們的常用的AOP它的底層實現原理所以大家一起加油加油&#xff01;&#xff01;&#xff01; AOP: 1.簡介: AOP的…

Linux(Centos 7.6)基本信息查看

1.服務器硬件信息查看 1.1.服務器廠商、產品名稱查看 dmidecode -s system-manufacturer&#xff1a;查看服務器廠商信息 dmidecode -s system-product-name&#xff1a;查看服務器產品名稱信息 1.Windows使用VMware安裝的Linux(Centos 7.6)后&#xff0c;服務器廠商、產品名…

多個圖片轉換為PDF文件

將多個圖片轉換為PDF文件在Python中可以通過多個庫來實現&#xff0c;其中最常用的庫之一是Pillow&#xff08;用于圖像處理&#xff09;和reportlab&#xff08;用于生成PDF&#xff09;。不過&#xff0c;對于直接圖片轉PDF的操作&#xff0c;更推薦使用Pillow配合PyMuPDF&am…

小程序app封裝公用頂部篩選區uv-drop-down

參考ui:DropDown 下拉篩選 | 我的資料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生態框架 樣式示例&#xff1a; 封裝公用文件代碼 dropDownTemplete <template><!-- 頂部下拉篩選區封裝公用組件 --><view><uv-drop-down ref&…

LeetCode:101. 對稱二叉樹

跟著carl學算法&#xff0c;本系列博客僅做個人記錄&#xff0c;建議大家都去看carl本人的博客&#xff0c;寫的真的很好的&#xff01; 代碼隨想錄 LeetCode&#xff1a;101. 對稱二叉樹 給你一個二叉樹的根節點 root &#xff0c; 檢查它是否軸對稱。 示例 1&#xff1a; 輸…

Docker-如何啟動docker

作者介紹&#xff1a;簡歷上沒有一個精通的運維工程師。希望大家多多關注作者&#xff0c;下面的思維導圖也是預計更新的內容和當前進度(不定時更新)。 我們在上一章&#xff0c;講了虛擬化&#xff0c;虛擬化是把硬件虛擬化&#xff0c;然后創建出來的虛擬機完全隔離&#xff…