I'm initializing my retrofit client in Base Application android class, and in MainActivity I'm using it to call api. Sometimes, the api call starts before Base class could initialize my retrofit client and it crashes the app. How do I check in MainActivity before making api call that if apiInterface client is initialized or not before making the rest api call?
I know that we can do this to check initialization for lateinit variables in a class.
::variable.isInitialized
But It's not working in this case as I access the static object like this BaseApp.apiInterface Here's my code:
BaseApp.kt
class BaseApp : Application() {
companion object {
lateinit var apiInterfaceLogin: ApiInterface
lateinit var apiInterface: ApiInterface
lateinit var okHttpClient: OkHttpClient.Builder
}
override fun onCreate() {
super.onCreate()
fetchPrefs()
initData()
}
private fun initData() {
val interceptor = Interceptor { chain ->
val newRequest = chain.request().newBuilder()
.addHeader("app-token", Constants.APP_TOKEN)
.addHeader("Cache-Control", "no-cache")
.build()
chain.proceed(newRequest)
}
okHttpClient = OkHttpClient.Builder()
okHttpClient.interceptors().add(interceptor)
val client = okHttpClient.build()
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(ApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
apiInterface = retrofit.create(ApiInterface::class.java)
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
companion object {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
checkShifts()
}
private fun checkShifts() {
val checkShiftsApiCall = BaseApp.apiInterface.startRun(BaseApp.userId)
checkShiftsApiCall.enqueue(object : Callback<MyAvailableShiftsResponse> {
override fun onResponse(call: Call<MyAvailableShiftsResponse>, response: Response<MyAvailableShiftsResponse>) {
}
override fun onFailure(call: Call<MyAvailableShiftsResponse>, t: Throwable) {
}
}
})
}
}
CodePudding user response:
You can expose it using additional property in BaseApp
companion:
val isApiInterfaceInitialized get() = ::apiInterface.isInitialized
As a side note, you can access properties of companion objects, but you need to reference them explicitly, for example:
BaseApp.Companion::apiInterface
Still, accessing isInitialized
is disallowed from outside the object as this is considered implementation details that apiInterface
is lateinit
.
Also, the main use case of lateinit
is when we are sure that we initialize it before the first use. If you need to always/often check it before use or you use it outside the object, then regular nullable property may be a better choice.