任何人都可以帮助我了解如何在 Kotlin 中生成 protobuf?我听说过gRPC
, wire
, KotlinPoet
, 但我不明白有什么区别,我应该使用哪个样本,任何简单的文件请填写免费与我分享?任何人都可以提供一个示例链接,该链接显示如何为 Kotlin 生成 Protobuf 示例?
问问题
1700 次
1 回答
2
我已经使用square/wire
和io.grpc
库与 gRPC 服务进行通信。的问题wire
是它还不支持 proto3 版本。
在这里,我将为您提供一个如何从io.grpc
.
假设有一个 gRPC 服务可以汇总您发送给它的数字流。它的原型文件会是这样的:
累加器.proto
syntax = "proto3";
package accumulator;
service Accumulator {
rpc NumberStream (stream NumberRequest) returns (stream AccumulateReply) {
}
}
message NumberRequest {
int32 number = 1;
}
message AccumulateReply {
int64 sumUp = 1;
}
你应该把这个文件放在/src/main/proto/
项目的目录下。
现在是时候将所需的依赖项添加到build.gradle
文件中了。请注意,它用于kapt
生成代码。
App Level 的 build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.protobuf'
apply plugin: 'kotlin-kapt'
android {
... others
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
}
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.10.0' }
plugins {
javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.25.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
all().each { task ->
task.plugins {
javalite {}
grpc { // Options added to --grpc_out
option 'lite'
}
}
}
}
}
dependencies {
... other dependencies
// ------- GRPC
def grpc_version = '1.25.0'
implementation "io.grpc:grpc-android:$grpc_version"
implementation "io.grpc:grpc-okhttp:$grpc_version"
implementation "io.grpc:grpc-protobuf-lite:$grpc_version"
implementation "io.grpc:grpc-stub:$grpc_version"
// ------- Annotation
def javax_annotation_version = '1.3.2'
implementation "javax.annotation:javax.annotation-api:$javax_annotation_version"
}
项目级别的 build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
... others
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
}
}
这是一个用服务器封装流活动的类。它通过回调返回接收到的值:
累加器处理程序.kt
import android.content.Context
import io.grpc.ManagedChannel
import io.grpc.android.AndroidChannelBuilder
import io.grpc.stub.ClientCallStreamObserver
import io.grpc.stub.StreamObserver
import accumulator.AccumulatorOuterClass
import java.util.concurrent.Executors
/**
* @author aminography
*/
class AccumulatorHandler constructor(
private val context: Context,
private val endPoint: String
) {
var callback: AccumulatorCallback? = null
private var managedChannel: ManagedChannel? = null
private var requestObserver: StreamObserver<AccumulatorOuterClass.NumberRequest>? = null
private val responseObserver: StreamObserver<AccumulatorOuterClass.AccumulateReply> =
object : StreamObserver<AccumulatorOuterClass.AccumulateReply> {
override fun onNext(value: AccumulatorOuterClass.AccumulateReply?) {
callback?.onReceived(value.sumUp)
}
override fun onError(t: Throwable?) {
callback?.onError(t)
}
override fun onCompleted() {
callback?.onCompleted()
}
}
fun offer(number: Int) {
initChannelIfNeeded()
requestObserver?.onNext(
AccumulatorOuterClass.NumberRequest.newBuilder()
.setNumber(number)
.build()
)
}
fun offeringFinished() {
requestObserver?.onCompleted()
}
private fun initChannelIfNeeded() {
if (managedChannel == null) {
managedChannel = AndroidChannelBuilder.forTarget(endPoint)
.context(context)
.usePlaintext()
.executor(Executors.newSingleThreadExecutor())
.build()
}
if (requestObserver == null) {
requestObserver = AccumulatorGrpc.newStub(managedChannel)
.withExecutor(Executors.newSingleThreadExecutor())
.numberStream(responseObserver)
}
}
fun release() {
(requestObserver as? ClientCallStreamObserver<*>)?.cancel("Cancelled by client.", null)
requestObserver = null
managedChannel?.shutdown()
managedChannel = null
callback = null
}
interface AccumulatorCallback {
fun onReceived(sum: Long)
fun onError(t: Throwable?)
fun onCompleted()
}
}
为了测试它,我编写了一个活动类来以简单的方式显示它的用法:
我的活动.kt
/**
* @author aminography
*/
class MyActivity: AppCompatActivity, AccumulatorHandler.AccumulatorCallback {
private var accumulatorHandler: AccumulatorHandler? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
accumulatorHandler = AccumulatorHandler(applicationContext, "http://...")
accumulatorHandler.callback = this
for (number in 1..10){
accumulatorHandler.offer(number)
}
accumulatorHandler.offeringFinished()
}
override fun onReceived(sum: Long) {
Toast.makeText(this, "onReceived: $sum", Toast.LENGTH_SHORT).show()
}
override fun onError(t: Throwable?) {
Toast.makeText(this, "onError: $t", Toast.LENGTH_SHORT).show()
accumulatorHandler.release()
}
override fun onCompleted() {
Toast.makeText(this, "onCompleted", Toast.LENGTH_SHORT).show()
accumulatorHandler.release()
}
}
于 2020-06-28T07:30:29.280 回答