{"id":50350487,"url":"https://github.com/MalekKamel/RxRequester","last_synced_at":"2026-06-15T12:01:39.083Z","repository":{"id":90820934,"uuid":"215377614","full_name":"MalekKamel/RxRequester","owner":"MalekKamel","description":"Simple \u0026 Clean RxJava requester for Android","archived":false,"fork":false,"pushed_at":"2020-01-23T10:04:56.000Z","size":2398,"stargazers_count":60,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-22T15:03:37.028Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MalekKamel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-15T19:14:54.000Z","updated_at":"2023-01-15T02:24:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"9e9ac146-e689-4e65-98f1-8d85966a8257","html_url":"https://github.com/MalekKamel/RxRequester","commit_stats":null,"previous_names":["malekkamel/rxrequester","shabankamell/rxrequester"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/MalekKamel/RxRequester","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MalekKamel%2FRxRequester","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MalekKamel%2FRxRequester/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MalekKamel%2FRxRequester/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MalekKamel%2FRxRequester/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MalekKamel","download_url":"https://codeload.github.com/MalekKamel/RxRequester/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MalekKamel%2FRxRequester/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34361403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T21:00:23.918Z","updated_at":"2026-06-15T12:01:39.078Z","avatar_url":"https://github.com/MalekKamel.png","language":"Kotlin","funding_links":[],"categories":["HTTP客户端"],"sub_categories":["微服务框架"],"readme":"RxReqeuster\n==============\n\n\u003cimg src=\"https://github.com/ShabanKamell/RxRequester/blob/master/blob/raw/logo.png\" height=\"200\"\u003e\n\nA wrapper for RxJava abstracts away all those nasty details you don't really care about in most requests and provides default configurations for schedulers, loading indicators, and error handling. \n\nUsing **RxRequester** you can:\n- [ ] Make clean RxJava requests.\n- [ ] Inline \u0026 Global error handling.\n- [ ] Toggle loading indicators easily.\n\n### Before RxRequester\n\n``` kotlin\nrestaurantsRepo.all()\n                .doOnSubscribe { showLoading() }\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.main())\n                .doOnNext { hideLoading() }\n                .subscribe( {\n\n                }, { error -\u003e\n\n                })\n```\n\n### After RxRequester\n\n``` kotlin\nrequester.request { restaurantsRepo.all() }.subscribe { }\n```\n\n#### Gradle:\n```groovy\nallprojects {\n    repositories {\n        ...\n        maven { url \"https://jitpack.io\" }\n    }\n}\n\ndependencies {\n        implementation 'com.github.ShabanKamell:RxRequester:x.y.z'\n}\n\n```\n(Please replace x, y and z with the latest version numbers:  [![](https://jitpack.io/v/ShabanKamell/RxRequester.svg)](https://jitpack.io/#ShabanKamell/RxRequester))\n\n## Setup\n\n``` kotlin\nval presentable = object: Presentable {\n    override fun showError(error: String) { .. }\n    override fun showError(error: Int) { .. }\n    override fun showLoading() { .. }\n    override fun hideLoading() { .. }\n    override fun onHandleErrorFailed(throwable: Throwable) { .. }\n}\n\nRxRequester.create(presentable) {\n  resumableHandlers = listOf(TokenExpiredHandler())\n  httpHandlers = listOf(ServerErrorHandler())\n  throwableHandlers = listOf(IoExceptionHandler(), NoSuchElementHandler(), OutOfMemoryErrorHandler())\n  serverErrorContract = ErrorContract::class.java\n}\n\n// Or provide error handlers this way:\n RxRequester.resumableHandlers = listOf(TokenExpiredHandler())\n RxRequester.httpHandlers =      listOf(ServerErrorHandler())\n RxRequester.throwableHandlers = listOf(OutOfMemoryErrorHandler())\n```\n\n## Error Handling\nThere're 3 types of error handlers in the library\n\n### 1- Resumable Handler\nThere're cases where you want to handle the error and resume the current request as normal. Resumable handler provides the easiest solution for this problem!\nImagine you received `401 token expired` error and you want to refresh the token then resume the original request. This can be done as easy as like this!\n\n```kotlin\nclass TokenExpiredHandler: ResumableHandler() {\n     // check if the error code is 401\n    override fun canHandle(info: ThrowableInfo): Boolean {\n        return (throwable as? HttpException)?.errorCode() == 401\n    }\n    // retrun the API that refreshes the token\n    override fun handle(throwable: Throwable, presentable: Presentable): Flowable\u003cAny\u003e {\n        return info.requester.request{ ServiceApi.refreshToken() }\n    }\n}\n```\nOf course you can apply this for any error you want.\n\n### 2- Retrofit Http Handler\nHandles Retrofit's HttpException\n\n``` kotlin\nclass ServerErrorHandler: HttpExceptionHandler() {\n\n    override fun supportedErrors(): List\u003cInt\u003e {\n        return listOf(500)\n    }\n\n    override fun handle(throwable: Throwable, presentable: Presentable, errorCode: Int, errorBody: String) {\n        presentable.showError(R.string.oops_something_went_wrong)\n    }\n}\n```\n\n### 3- Throwable Handler\nhandles generic Throwables\n\n``` kotin\nclass OutOfMemoryErrorHandler: ThrowableHandler\u003cOutOfMemoryError\u003e() {\n\n    override fun supportedErrors(): List\u003cClass\u003cOutOfMemoryError\u003e\u003e {\n        return listOf(OutOfMemoryError::class.java)\n    }\n\n    override fun handle(throwable: Throwable, presentable: Presentable) {\n        presentable.showError(R.string.no_memory_free_up_space)\n    }\n}\n```\n\n## Error Handlers Priority\nThe library handles errors according to this priority\n##### 1- Resumable Handlers\n##### 2- HTTP Handlers\n##### 3- Throwable Handlers\n\nThe library first asks Resumable handlers to handle the error, if can't handle it will be passed to HTTP handlers, if can't handle, the error will be passed to Throwable hanldlers. If no handler can handle the error, it will be passed to `Presentable.onHandleErrorFailed(Throwable)`\n\n## Server Error Contract\nRxRequester optionally parses server error for you and shows the error automatically. Just implement `ErrorMessage`\ninterface in your server error model and return the error message.\n\n``` kotlin\ndata class ErrorContract(private val message: String): ErrorMessage {\n    override fun errorMessage(): String {\n        return message\n    }\n}\n// Pass the contract\nval requester = RxRequester.create(ErrorContract::class.java, presentable)\n```\n\n## Customizing Requests\nRxRequester gives you the full controll over any request\n- [ ] Inline error handling\n- [ ] Enable/Disable loading indicators\n- [ ] Set subscribeOn Scheduler\n- [ ] Set observeOn Scheduler\n\n``` kotlin\n val requestInfo = RequestOptions.Builder()\n         .inlineErrorHandling { false }\n         .showLoading(true)\n         .subscribeOnScheduler(Schedulers.io())\n         .observeOnScheduler(AndroidSchedulers.mainThread())\n         .build()\n\n requester.request(requestOptions) { dm.restaurantsRepo.all() }\n```\n\nHere're all request options and default values\n\n|          **Option**          |         **Type**          |          **Default**           |\n| ---------------------------- | --------------------------|------------------------------- |\n| **inlineHandling**           | ((Throwable) -\u003e Boolean)? | null                           |\n| **showLoading**              | Boolean                   | true                           |\n| **subscribeOnScheduler**     | Scheduler                 | Schedulers.io()                |\n| **observeOnScheduler**       | Scheduler                 | AndroidSchedulers.mainThread() |\n\n### Best Practices\n- [ ] Setup `RxRequester` only once in `BaseViewModel` and reuse in the whole app.\n- [ ] Initialize error handlers only once. You can initialize then Application class as they are static properties.\n\n#### Look at 'sample' module for the full code. For more advanced example, [Restaurants Modular Architecture](https://github.com/ShabanKamell/Restaurants)\n\n### License\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMalekKamel%2FRxRequester","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMalekKamel%2FRxRequester","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMalekKamel%2FRxRequester/lists"}