Skip to content

Instantly share code, notes, and snippets.

View timusus's full-sized avatar

Tim Malseed timusus

  • Australian Broadcasting Corporation
  • Hobart, Tasmania
  • 03:40 (UTC +10:00)
View GitHub Profile
@timusus
timusus / CallResultAdapterFactory.kt
Last active March 24, 2023 16:10
Retrofit Error Handling
import retrofit2.Call
import retrofit2.CallAdapter
import retrofit2.Response
import retrofit2.Retrofit
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.concurrent.Executor
class CallResultAdapterFactory(private val responseErrorMapper: ((Response<*>) -> Error?)? = null) : CallAdapter.Factory() {
@timusus
timusus / ElapsedTimeIdlingResource.kt
Created November 30, 2021 00:36
Compose Elapsed Time Idling Resource
import androidx.compose.ui.test.IdlingResource
/**
* An [IdlingResource] which reports itself as idle until [waitingTime] has elapsed.
*/
class ElapsedTimeIdlingResource(private val waitingTime: Long) : IdlingResource {
var startTime: Long = System.currentTimeMillis()
override val isIdleNow: Boolean
@timusus
timusus / AndroidMediaService.java
Last active October 6, 2021 07:09
Example of a media playback Service
//This file represents several classes. It's just named *.java for syntax highlighting purposes!
//AIDL file: Defines interfaces for communicating between activities and your service.
//You can see these implemented in the service @ 'private static class ServiceStub extends IPlaybackService.Stub'
interface IPlaybackService {
void stop();
void play();
@timusus
timusus / HomeContract.kt
Last active April 21, 2020 10:53
Shuttle - Home Contract
// This Gist demonstrates the use of MVP in an Android project.
// File 1 - The contract. Defines the View and Presenter interface.
// File 2 - The Presenter implementation
// File 3 - The View implementation (ViewController / Fragment)
// I like this architecture because it helps with separation of concerns. The business logic is carried out
// in the Presenter, which has no (or limited) knowledge of Android framework components (which also makes it easier to test)
// The View Controller (Fragment) is then kept very lightweight, and only deals with updating views and dispatching
@timusus
timusus / EqualizerAudioProcessor.kt
Last active November 16, 2019 01:47
EqualizerAudioProcessor
class EqualizerAudioProcessor : BaseAudioProcessor() {
lateinit var prevXArray: Array<ShortArray>
lateinit var prevYArray: Array<ShortArray>
override fun configure(sampleRateHz: Int, channelCount: Int, encoding: Int): Boolean {
val flush = setInputFormat(sampleRateHz, channelCount, encoding)
prevXArray = Array(channelCount) { ShortArray(2) { 0 } }
prevYArray = Array(channelCount) { ShortArray(2) { 0 } }
/**
* Executes a unit of work at a specified interval.
*
* An attempt threshold can be specified. If the number of attempts to execute the work exceeds this threshold, `didExceedAttemptThreshold()` is called and the timer is
* invalidated.
*
* An error threshold can also be specified. If the number of errors exceeds this threshold, `didExceedErrorThreshold()` is called, and the latest error is passed in.
*
* Note: This class uses a Timer to execute the work, ensure to call `stop()` when no longer interested in the result, or a leak may occur.
*
@timusus
timusus / UserDescriptionSnippet.kt
Last active October 20, 2018 03:58
Error to user description
fun Error.userDescription(): String {
return when (this) {
is RemoteServiceHttpError ->
return when {
isServerError -> "A server error occurred. (${httpStatusCode.code})"
else -> "An error occurred. (${httpStatusCode.code})"
}
}
is OAuthError -> {
return "Authentication failed."
@timusus
timusus / ResponseMapperSnippet.kt
Last active October 20, 2018 03:57
ResponseMapperSnippet
override fun onResponse(call: Call<T>, response: Response<T>) {
if (call.isCanceled) return
if (response.isSuccessful) {
callback(Result.Success(response.body()))
} else {
callback(Result.Failure(responseErrorMapper?.invoke(response) ?: RemoteServiceHttpError(response)))
}
}
call.enqueue {
override fun onResult(result: Result) {
when(result){
is Success -> {
// Handle Success
}
is Failure -> {
presentAlert(
title = "Login Failed",
message = result.error.userDescription()
val responseErrorMapper: (retrofit2.Response<*>) -> Error? = { response ->
// Todo: Map response into your custom error type
}