Home > database >  Context.getApplicationContext()' on a null object when using OkHttp cache
Context.getApplicationContext()' on a null object when using OkHttp cache

Time:01-15

I'm trying to cache my data from API using oKhttp and save this data into FILE. The problem is when I'm trying to use applicationContext.cacheDir, in my NetworkLayer class but it gives me an error.

  • I have tried to make my NetworkLayer extends from Application() but the problem is still.

  • I also tried to make some search about this problem but I didn't find anything that related. Thanks In advance.

Here's my code


NetworkLayer

class NetworkLayer : Application() {

private val BASE_URL = ""
private val moshi: Moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()

private fun myHttpClient(): OkHttpClient {
    val interceptor = HttpLoggingInterceptor()
    interceptor.level = HttpLoggingInterceptor.Level.BODY

    val httpCacheDirectory = File(applicationContext.cacheDir, "http-cache")
    val cacheSize = 10 * 1024 * 1024 // 10 MiB
    val cache = Cache(httpCacheDirectory, cacheSize.toLong())

    val builder = OkHttpClient()
        .newBuilder()
        .addNetworkInterceptor(CacheInterceptor())
        .cache(cache)
        .addInterceptor(interceptor)
        .callTimeout(3, TimeUnit.SECONDS)
        .connectTimeout(3, TimeUnit.SECONDS)
    return builder.build()
}

private val retrofit: Retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(myHttpClient())
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

val apiService: APIService by lazy {
    retrofit.create(APIService::class.java)
   }
}

The problem is here, at this code line

  • val httpCacheDirectory = File(applicationContext.cacheDir, "http-cache")

My CacheInterceptor Class

class CacheInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
    val response: Response = chain.proceed(chain.request())
    val cacheControl = CacheControl.Builder()
        .maxAge(1, TimeUnit.DAYS)
        .build()
    return response.newBuilder()
        .removeHeader("Pragma")
        .removeHeader("Cache-Control")
        .header("Cache-Control", cacheControl.toString())
        .build()
    }
}

The Error message

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.moataz.afternoonhadeeth/com.moataz.afternoonhadeeth.ui.view.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3430)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3614)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:86)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
    at android.os.Handler.dispatchMessage(Handler.java:112)
    at android.os.Looper.loop(Looper.java:216)
    at android.app.ActivityThread.main(ActivityThread.java:7625)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
    at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:116)
    at com.moataz.afternoonhadeeth.data.request.NetworkLayer.myHttpClient(NetworkLayer.kt:26)
    at com.moataz.afternoonhadeeth.data.request.NetworkLayer.<init>(NetworkLayer.kt:42)
    at com.moataz.afternoonhadeeth.data.repository.ApiClient.<init>(ApiClient.kt:12)
    at com.moataz.afternoonhadeeth.ui.viewmodel.HomeViewModel.<init>(HomeViewModel.kt:16)
    at com.moataz.afternoonhadeeth.ui.view.fragment.HomeFragment.<init>(HomeFragment.kt:25)
    at com.moataz.afternoonhadeeth.ui.view.activity.MainActivity.initializeBottomNavigation(MainActivity.kt:71)
    at com.moataz.afternoonhadeeth.ui.view.activity.MainActivity.onCreate(MainActivity.kt:46)
    at android.app.Activity.performCreate(Activity.java:7458)
    at android.app.Activity.performCreate(Activity.java:7448)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1286)

Edit: Here's the final code

class NetworkLayer : AppCompatActivity() {

private val BASE_URL = ""
private val moshi: Moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
private val myHttpClient = OkHttpClient()

override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
    super.onCreate(savedInstanceState, persistentState)
    val interceptor = HttpLoggingInterceptor()
    interceptor.level = HttpLoggingInterceptor.Level.BODY

    val httpCacheDirectory = File(applicationContext.cacheDir, "http-cache")
    val cacheSize = 10 * 1024 * 1024 // 10 MiB
    val cache = Cache(httpCacheDirectory, cacheSize.toLong())

    myHttpClient
        .newBuilder()
        .addNetworkInterceptor(CacheInterceptor())
        .addInterceptor(ForceCacheInterceptor())
        .cache(cache)
        .callTimeout(3, TimeUnit.SECONDS)
        .connectTimeout(3, TimeUnit.SECONDS)
        .build()
}

private val retrofit: Retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(myHttpClient)
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

val apiService: APIService by lazy {
    retrofit.create(APIService::class.java)
    }
}

CodePudding user response:

applicationContext.cacheDir must call after onCreate() in Application class.

In your code myHttpClient() is calling before onCreate() so applicationContext is null.

To solve this problem you can create retrofit in Application onCreate()

  •  Tags:  
  • Related