改进版2.6.0:自定义协程CallAdapterFactory

时间:2019-08-23 11:17:41

标签: android retrofit retrofit2 kotlin-coroutines retrofit2.6

我需要在我的api中进行自定义错误处理,并且我想在新版本的Retrofit中使用协程。由于我们不再需要使用Deferred,因此我们自己的杰克·沃顿(Jake Wharton)一个月前在reddit上撰写了此内容

enter image description here

https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/RxJavaObserveOnMainThread.java

但是我在正确创建CallAdapterFactory时遇到了问题。

具体来说,我不明白:“委托给内置工厂,然后将值包装在密封类中”

有没有人正在使用此设置可以提供帮助?

这是当前代码

sealed class Results<out T: Any> {
    class Success<out T: Any>(val response: T): Results<T>()
    class Failure(val message: String, val serverError: ServerError?): Results<Nothing>()
    object NetworkError: Results<Nothing>()
}


class ResultsCallAdapterFactory private constructor() : CallAdapter.Factory() {

    companion object {
        @JvmStatic
        fun create() = ResultsCallAdapterFactory()
    }

    override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? {
        return try {
            val enclosedType = returnType as ParameterizedType
            val responseType = getParameterUpperBound(0, enclosedType)
            val rawResultType = getRawType(responseType)
            val delegate: CallAdapter<Any,Any> = retrofit.nextCallAdapter(this,returnType,annotations) as CallAdapter<Any,Any>
            if(rawResultType != Results::class.java)
                null
            else {
                object: CallAdapter<Any,Any>{
                    override fun adapt(call: Call<Any>): Any {
                         val response = delegate.adapt(call)
                        //What should happen here?
                        return response
                    }

                    override fun responseType(): Type {
                        return delegate.responseType()
                    }

                }
            }
        } catch (e: ClassCastException) {
            null
        }

    }
}

2 个答案:

答案 0 :(得分:9)

这是一个可行的示例。 GitHub示例也是available

#include <iostream>
using namespace std;

class Enemy
{
    public:
    Enemy() {}
    void attack() 
    {
        cout << "attack";
    }
};

#define VERSION 1

int main(int argc, char* argv[]) {
    Enemy e;
#if VERSION == 1
    e.attack();
#elif VERSION == 2
    Enemy& e2 = e;
    e2.attack();
#else
    Enemy* e3 = &e;
    e3->attack();
#endif
}
// build.gradle

...
dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
    implementation 'com.google.code.gson:gson:2.8.5'
}

答案 1 :(得分:1)

我已经创建了这样一个工厂的示例,您可以在 here on GitHub 中找到它。另请看一个类似的问题:How to create a call adapter for suspending functions in Retrofit?.