Android 存盤方式
SharedPrefence,存盤簡單的配置資料等
SQLite,存盤復雜的關系型資料
File,一般存盤日志檔案,本地檔案快取, protobuf ,7z
ContentProvider,跨行程資料訪問,一般和SQLite結合使用,把資料提供給其他app行程使用,
網路存盤,網路存盤涉及到序列化/反序列化(protobuf,xml,json)
SharedPrefence
SharedPrefence的commit和apply
- apply沒有回傳值,而commit回傳boolean表明修改是否提交成功 ;
- commit是把內容同步提交到硬碟的,而apply先立即把修改提交到記憶體,然后開啟一個異步的執行緒提交到硬碟,并且如果提交失敗,你不會收到任何通知,
- 所有commit提交是同步程序,效率會比apply異步提交的速度慢,在不關心提交結果是否成功的情況下,優先考慮apply方法,
- apply是使用異步執行緒寫入磁盤,commit是同步寫入磁盤,所以我們在主執行緒使用的commit的時候,需要考慮是否會出現ANR問題,(不適合大量資料存盤)
多行程問題 -> mmkv
SQLite
- SQLiteStatement
- 使用事務
- 使用索引
- 異步執行緒,寫資料庫統一管理
多執行緒環境中,如果每個執行緒都單獨進行寫資料庫,性能低下,因此,為了提高性能,一般使用資料佇列,多執行緒將資料寫入資料佇列,異步執行緒批量寫資料庫,
網路
- 序列化
- 反序列化
xml
json
protobuf 與平臺無關
7z壓縮 (作業)
protobuf
已經有xml/json,為什么要用protobuf
相對于xml,json,protobuf的優點:
- 簡潔:xml要寫一大堆決議的代碼,而protobuf自動生成代碼,使用時只需要寫簡介的代碼呼叫即可,
- 體積小:訊息大小只有xml的1/10 - 1/3
- 速度快:決議速度比xml快20~100倍
- 使用Protobuf編譯系統: 可以生成更容易在編程中使用的資料訪問代碼
- 更好的兼容性,Protocol Buffers設計的一個原則就是要能夠很好的支持向下或向上兼容,
缺點:
- 二進制格式導致可讀性差
為了提高性能,protobuf采用了二進制格式進行編碼,這直接導致了可讀性差,這個直接影響開發測驗時候的效率,當然,一般情況下,protobuf非常可靠,并不會出現太大的問題, - 缺乏自描述
一般來說,XML是自描述的,而protobuf格式則不是,給你一段二進制格式的協議內容,不配合你寫的結構體是看不出來什么作用的,
專案中使用protobuf
在命令列中使用protobuf
如果要用命令將protobuf檔案(protobuf檔案的后綴為.proto)編譯為java檔案,需要安裝protobuf工具,然后使用protoc 命令進行編譯,
在Android studio專案中使用protobuf
1)首先,我們需要在全域的buid.gradle檔案中添加上protobuf工具插件:
classpath ‘com.google.protobuf:protobuf-gradle-plugin:0.8.10’
2)然后,要app/buid.gradle檔案中:
①添加上此插件
apply plugin: 'com.google.protobuf'
②添加依賴
implementation 'com.google.protobuf:protobuf-java:3.7.1'
③添加protobuf 配置
protobuf {
//配置protoc編譯器
protoc {
artifact = 'com.google.protobuf:protoc:3.7.1'
}
//這里配置生成目錄,編譯后會在build的目錄下生成對應的java檔案
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.builtins {
java {}
}
}
}
}
④添加 protobuf檔案的目錄(在android {}里面)
sourceSets {
main {
proto {
srcDir 'src/main/java/com/protobufdir'
}
}
}
3)在src/main/java/com/protobufdir目錄下新建protobufbean.proto檔案,添加如下代碼:
syntax = "proto3";
package com.example.protobufdemo;//包名
option java_package = "com.example.protobuf02";
option java_outer_classname = "Person";
option csharp_namespace = "android";
message _Person{
string name = 1;
int32 id = 2;
string email = 3;
enum _PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message _PhoneNumber{
string number =1;
_PhoneType type = 2;
}
repeated _PhoneNumber phone = 4;//陣列
}
4) 重新build專案,AS build專案時,會將.proto檔案生成java檔案,
可以在\app\build\generated\source\proto\debug\java\ 目錄下找到這些生成的java檔案,
這些生成的java檔案封裝好了一些序列化和反序列化的API ,這些API 可以直接在專案中呼叫 ,
語言規范
訊息定義
- 確定訊息命名,給訊息取一個有意義的名字,
- 指定欄位的型別
- 定義欄位的編號,在Protocol Buffers中,欄位的編號非常重要,欄位名僅僅是作為參考和生成代碼用,需要注意的是欄位的編號區間范圍,其中19000 ~19999被Protocol Buffers作為保留欄位,
欄位約束
- required指定該欄位必須賦值,禁止為空(在v3中該約束被移除);
- optional指定欄位為可選欄位,可以為空,對于optional欄位還可以使用[default]指定默認值,如果沒有指定,則會使用欄位型別的默認值;
- 使用repeated指定欄位為集合
欄位型別
- 在一個proto檔案中可以同時定義多個message型別,生成代碼時根據生成代碼的目標語言不同,處理的方式不太一樣,如Java會針對每個message型別生成一個.java檔案
- 可以指定欄位的型別為其他message型別
- 使用import關鍵字匯入其他proto檔案
- 在proto檔案中訊息的型別還可以嵌套
- 在proto檔案中可以使用extensions關鍵字預留一部分欄位編號出來,以便于后期給第三方擴展時使用
- oneof關鍵字指定一組欄位中,至少要有一個欄位必須賦值
在Protocol Buffers中提供了很多的標量型別,供我們在定義欄位型別時使用:

編碼協議
Base-128變長編碼
- 所謂變長編碼是和定長編碼相對的,定長編碼使用固定位元組數來表示,如int32型別的數字固定使用4 bytes表示,而變長編碼是需要幾個位元組就使用幾個位元組,如對于int32型別的數字1來說,只需要1 bytes足夠,Base-128變長編碼的原則就兩條
- 每個位元組使用使用低7位表示數字,除了最后一個位元組,其他位元組的最高位都設定為1,
- 采用Little-Endian位元組序
- tag-length-valuetag-length-value

負數編碼處理
- 采用ZigZag Encoding
(n <<1)^(n>>31)或者(n<<1)^(n>>63)
大端序列
先寫高位,再寫低位
小端序列
先寫低位,再寫高位
Protocol Buffers 序列化協議及應用
【Protobuf】Protobuf的編解碼規則詳解
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/192746.html
標籤:其他
上一篇:1024,節日快樂!
