All Projects → jaychang0917 → Simpleapiclient

jaychang0917 / Simpleapiclient

Licence: apache-2.0
A configurable api client based on Retrofit2 and RxJava2 for android

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to Simpleapiclient

Eve
Eve and Wall-e
Stars: ✭ 133 (-8.9%)
Mutual labels:  rxjava2, retrofit2
Rxapp
Stars: ✭ 108 (-26.03%)
Mutual labels:  rxjava2, retrofit2
Android Kotlin Mvp Clean Architecture
Clean architecture blueprint using Kotlin and MVP pattern.
Stars: ✭ 105 (-28.08%)
Mutual labels:  rxjava2, retrofit2
Rxcore
开发框架基于RxJava2+Retrofit2
Stars: ✭ 135 (-7.53%)
Mutual labels:  rxjava2, retrofit2
Phoenix For Vk
Yet another VK client for Android
Stars: ✭ 131 (-10.27%)
Mutual labels:  rxjava2, retrofit2
Mvpframes
整合大量主流开源项目并且可高度配置化的 Android MVP 快速集成框架,支持 AndroidX
Stars: ✭ 100 (-31.51%)
Mutual labels:  rxjava2, retrofit2
Bilisoleil Kotlin
An unofficial bilibili client for android --kotlin+rxjava2+mvp+okhttp3+retrofit2+dagger2
Stars: ✭ 139 (-4.79%)
Mutual labels:  rxjava2, retrofit2
Gankioclient
利用干货集中营的API自制练手之作
Stars: ✭ 63 (-56.85%)
Mutual labels:  rxjava2, retrofit2
Roomrxjava
Room with Rxjava Example
Stars: ✭ 130 (-10.96%)
Mutual labels:  rxjava2, retrofit2
Android Cnblogs
🔥🔥 博客园Android端开源项目,界面简洁清新。
Stars: ✭ 127 (-13.01%)
Mutual labels:  rxjava2, retrofit2
Xsnow
💮基于RxJava2+Retrofit2精心打造的Android基础框架,包含网络、上传、下载、缓存、事件总线、权限管理、数据库、图片加载,基本都是项目中必用功能,每个模块充分解耦,可自由拓展。
Stars: ✭ 1,678 (+1049.32%)
Mutual labels:  rxjava2, retrofit2
Dagger2
Kotlin Dagger2 example project
Stars: ✭ 145 (-0.68%)
Mutual labels:  rxjava2, retrofit2
Open Source Android Weather App
☔️ Open source android weather app. See "Issues" tab for current tasks queue. Tasks suitable for beginners are labeled with green "beginner friendly" tags.
Stars: ✭ 81 (-44.52%)
Mutual labels:  rxjava2, retrofit2
Kotlinmvpsamples
🚀(Kotlin 版 )快速搭建 Kotlin + MVP + RxJava + Retrofit + EventBus 的框架,方便快速开发新项目、减少开发成本。
Stars: ✭ 103 (-29.45%)
Mutual labels:  rxjava2, retrofit2
Wanandroid
🔥项目采用 Kotlin 语言,基于 MVP + RxJava + Retrofit + Glide + EventBus 等架构设计,努力打造一款优秀的 [玩Android] 客户端
Stars: ✭ 1,223 (+737.67%)
Mutual labels:  rxjava2, retrofit2
Redgram For Reddit
An Open-Sourced Android Reddit Client
Stars: ✭ 106 (-27.4%)
Mutual labels:  rxjava2, retrofit2
Aiyagirl
🔥 爱吖妹纸(含 Kotlin 分支版本)——Retrofit + RxJava + MVP 架构 APP 体验代码家的干货集中营 Gank.io,福利多多,不容错过
Stars: ✭ 1,109 (+659.59%)
Mutual labels:  rxjava2, retrofit2
Weatherapplication
A WeatherApplication with usage of different libraries of Android.
Stars: ✭ 61 (-58.22%)
Mutual labels:  rxjava2, retrofit2
Mvproute
Android Mvp模式迅速开发框架
Stars: ✭ 117 (-19.86%)
Mutual labels:  rxjava2, retrofit2
Armscomponent
📦 A complete android componentization solution, powered by MVPArms (MVPArms 官方快速组件化方案).
Stars: ✭ 1,664 (+1039.73%)
Mutual labels:  rxjava2, retrofit2

SimpleApiClient

Download Android Weekly

A configurable api client based on Retrofit2 and RxJava2 for android

Table of Contents

Installation

In your app level build.gradle :

dependencies {
    implementation 'com.jaychang:simpleapiclient:2.3.0'
    // if you use gson
    implementation 'com.jaychang:simpleapiclient-jsonparser-gson:2.3.0'
    // if you use moshi
    implementation 'com.jaychang:simpleapiclient-jsonparser-moshi:2.3.0'
}

Basic Usage

Step 1

Config the api client and use it to create your api.

interface GithubApi {

  companion object {
    fun create() : GithubApi =
      SimpleApiClient.create {
        baseUrl = "https://api.github.com"

        defaultParameters = mapOf()
        defaultHeaders = mapOf()
        connectTimeout = TimeUnit.MINUTES.toMillis(1)
        readTimeout = TimeUnit.MINUTES.toMillis(1)
        writeTimeout = TimeUnit.MINUTES.toMillis(1)
        logLevel = LogLevel.BASIC // default NONE
        isMockResponseEnabled = true // default false
        certificatePins = listOf(
          CertificatePin(hostname = "api.foo.com", sha1PublicKeyHash = "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"),
          CertificatePin(hostname = "api.bar.com", sha256PublicKeyHash = "fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9")
        )

        interceptors = listOf()
        networkInterceptors = listOf()
        httpClient = OkHttpClient.Builder().build() // your own http client

        jsonParser = MoshiJsonParser()
        errorClass = ApiError::class // should be conformed to SimpleApiError
        errorMessageKeyPath = "meta.message"
        errorHandler = { error ->
          // you can centralize the handling of general error here
          when (error) {
            is AuthenticationError -> {...}
            is ClientError -> {...}
            is ServerError -> {...}
            is NetworkError -> {...}
            is SSLError -> {...}
          }
        }
      }
  }

  @GET("/search/users")
  fun getUsers(@Query("q") query: String): Single<List<User>>

}

Step 2

Use observe() to enqueue the call, do your stuff in corresponding parameter block. All blocks are run on android main thread by default and they are optional.

githubApi.getUsers("google")
  .observe(
    onStart = { println("show loading") },
    onEnd = { println("hide loading") },
    onSuccess = { println(it) },
    onError = { println(it.message) }
  )

Unwrap Response by KeyPath

Sometimes the api response includes metadata that we don't need, but in order to map the response we create a wrapper class and make the function return that wrapper class. This approach leaks the implementation of service to calling code.

Assuming the response json looks like the following:

{
  total_count: 33909,
  incomplete_results: false,
  foo: {
    bar: {
      items: [
        {
          login: "jaychang0917",
          ...
        }
        ...
      ]
    }
  }
}

And you only want the items part, use @KeyPathResponse("keypath") annotation to indicate which part of response you want.

@GET("/search/users")
@KeyPathResponse("foo.bar.items")
fun getUsers(@Query("q") query: String): Single<List<User>>

Similarly, unwrap the error response by setting the errorMessageKeyPath of SimpleApiClient.Config

Unwrap Response by Wrapper Class

An alternative solution is that you can create a wrapper class that conforming SimpleApiResult<T>, and use @WrappedResponse(class) to indicate that you want an unwrapped response of that wrapper class.

class ApiResult<T: Any>: SimpleApiResult<T> {
  ...
}

@GET("/search/users")
@WrappedResponse(ApiResult::class)
fun getUsers(@Query("q") query: String): Single<List<User>>

Serial / Concurrent Calls

Serial

githubApi.foo()
  .then { foo -> githubApi.bar(foo.name) }
  .observe(...)

Serial then Concurrent

githubApi.foo()
  .then { foo -> githubApi.bar(foo.name) }
  .thenAll( bar ->
    githubApi.baz(bar.name),
    githubApi.qux(bar.name)
  )
  .observe(...)

Concurrent

SimpleApiClient.all(
  githubApi.foo(),
  githubApi.bar()
).observe(...)

Concurrent then Serial

SimpleApiClient.all(
  githubApi.foo(),
  githubApi.bar()
).then { array -> // the return type is Array<Any>, you should cast them, e.g. val users = array[0] as List<User>
  githubApi.baz()
}.observe(...)

Retry Interval / Exponential backoff

githubApi.getUsers("google")
  .retryInterval(maxRetryCount = 3, delaySeconds = 5) // retry up to 3 times, each time delays 5 seconds
  .retryExponential(maxRetryCount = 3, delaySeconds = 5) // retry up to 3 times, each time delays 5^n seconds, where n = {1,2,3}
  .observe(...)

Call Cancellation

Auto Call Cancellation

The api call will be cancelled automatically in corresponding lifecycle callback. For instance, an api call is made in onStart(), it be will cancelled automatically in onStop.

githubApi.getUsers("google")
  .autoDispose(this)
  .observe(...)

Cancel call manually

val call = githubApi.getUsers("google").observe(...)

call.dispose()

Mock Response

To enable response mocking, set SimpleApiClient.Config.isMockResponseEnabled to true.

Mock sample json data

To make the api return a successful response with provided json

@GET("/repos/{user}/{repo}")
@MockResponse(R.raw.get_repo)
fun getRepo(@Path("user") user: String, @Path("repo") repo: String): Single<Repo>

Mock status

To make the api return a client side error with provided json

@GET("/repos/{user}/{repo}")
@MockResponse(json = R.raw.get_repo_error, status = Status.CLIENT_ERROR)
fun getRepo(@Path("user") user: String, @Path("repo") repo: String): Single<Repo>

json parameter of MockResponse is optional, you can set the status only, then you receive empty string.

Possible Status values:

enum class Status {
  SUCCESS, AUTHENTICATION_ERROR, CLIENT_ERROR, SERVER_ERROR, NETWORK_ERROR, SSL_ERROR
}

To mock a response with success status only, you should return Completable.

@DELETE("/repo/{id}}")
@MockResponse(status = Status.SUCCESS)
fun deleteRepo(@Path("id") id: String): Completable

License

Copyright 2017 Jay Chang

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].