Kotlin: Okhttpclient правильный способ создания одного экземпляра?OkHttpClient не проходит проверку ip сервера? - PullRequest
0 голосов
/ 20 сентября 2019

Я новичок в разработке android kotlin и сейчас пытаюсь решить, как правильно создать отдельный экземпляр OkHttpClient для использования в приложениях.В настоящее время я вроде * создал отдельный экземпляр клиента и использовал его для связи с сервером, однако в настоящее время внутренний сервер не использует токен / идентификатор пользователя для проверки, а для проверки IP.Я могу войти в систему без проблем, но после перехода к другому действию, пытающемуся вызвать api, доступ к серверу блокируется, потому что, по-видимому, IP-адрес не совпадает.Я использовал POSTMAN, а также уже создал такое же работающее приложение для iOS, которое работает без проблем.Итак, мой вопрос, я создаю один экземпляр OkHttpClient неправильно?Или OkHttpClient не подходит для такой системы ipcheck?Должен ли я использовать другую библиотеку, и если да, какие-либо предложения и примеры?

Заранее спасибо

В настоящее время я пытался создать ее следующим образом:

class MyApplication: Application(){
    companion object{
        lateinit var client: OkHttpClient
    }
    override fun onCreate(){
        super.onCreate()
        client = OkHttpClient()
    }
}

Затем я создалвспомогательный класс для него:

class OkHttpRequest {
    private var client : OkHttpClient = MyApplication.client

    fun POST(url: String, parameters: HashMap<String, String>, callback: Callback): Call {
        val builder = FormBody.Builder()
        val it = parameters.entries.iterator()
        while (it.hasNext()) {
            val pair = it.next() as Map.Entry<*, *>
            builder.add(pair.key.toString(), pair.value.toString())
        }
        val formBody = builder.build()
        val request = Request.Builder()
            .url(url)
            .post(formBody)
            .build()


        val call = client.newCall(request)
        call.enqueue(callback)
        return call
    }

    fun GET(url: String, callback: Callback): Call {
        val request = Request.Builder()
            .url(url)
            .build()

        val call = client.newCall(request)
        call.enqueue(callback)
        return call
    }
}

Наконец, я использую его следующим образом:

val loginUrl = MyApplication.postLoginUrl
var userIdValue = user_id_textfield.text.toString()
var passwordValue = password_textfield.text.toString()

val map: HashMap<String, String> = hashMapOf("email" to userIdValue, "password" to passwordValue)

var request = OkHttpRequest()
request.POST(loginUrl, map, object : Callback {
val responseData = response.body?.string()
    // do something with response Data
}

И на другой активности после входа пользователя в систему:

val getPaidTo = MyApplication.getPaidTo
var request = OkHttpRequest()

request.GET(getPaidTo, object: Callback{
    //do something with data
}

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

Во-первых, не используйте ваш OkHttpClient непосредственно в каждом действии или фрагменте, используйте DI и перенесите всю свою бизнес-логику в репозиторий или какой-либо источник данных.

Здесь я поделюсь некоторым простым способом сделатьЗапрос REST с Retrofit, OkHttpClient и Koin, если вы хотите использовать одно и то же:

WebServiceModule:

val webServiceModule = module {
    //Create HttpLoggingInterceptor
    single { createLoggingInterceptor() }
    //Create OkHttpClient
    single { createOkHttpClient(get()) }
    //Create WebServiceApi
    single { createWebServiceApi(get()) }
}

/**
 * Setup a Retrofit.Builder and create a WebServiceApi instance which will hold all HTTP requests
 *
 * @okHttpClient Factory for HTTP calls
 */
private fun createWebServiceApi(okHttpClient: OkHttpClient): WebServiceApi {
    val retrofit = Retrofit.Builder()
        .baseUrl(BuildConfig.REST_SERVICE_BASE_URL)
        .client(okHttpClient)
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .build()
    return retrofit.create(WebServiceApi::class.java)
}

/**
 * Create a OkHttpClient which is used to send HTTP requests and read their responses.
 *
 * @loggingInterceptor logging interceptor
 */
private fun createOkHttpClient(
    loggingInterceptor: HttpLoggingInterceptor
): OkHttpClient {
    return OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .readTimeout(defaultTimeout, TimeUnit.SECONDS)
        .connectTimeout(defaultTimeout, TimeUnit.SECONDS)
        .build()
}

И теперь вы можете внедрить свой WebServiceApi везде, но лучше добавить его в свой репозиторий изатем используйте его из некоторого ViewModel

ViewModelModule:

val viewModelModule = module {
    //Create an instance of MyRepository 
    single { MyRepository(webServiceApi = get()) }
}

Надеюсь, что это поможет как-то

0 голосов
/ 23 сентября 2019

Хорошо, после проверки с внутренним разработчиком я обнаружил, что проблема не в IP-адресе (он остается прежним), а в том, что okhttp не сохранил файл cookie, и POSTMan, и xcode автоматически сохраняют токенвернулся в cookie, поэтому я никогда не замечал, что это была проблема.Так что после небольшого поиска в Google решение может быть таким простым:

class MyApplication : Application(){
    override fun onCreate(){
    val cookieJar = PersistentCookieJar(SetCookieCache(),SharedPrefsCookiePersistor(this))

    client = OkHttpClient.Builder()
        .cookieJar(cookieJar)
        .build()
    }
}

С добавлением persistentCookieJar в gradle.

...