Issue
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)
}
}
Solution
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()
Answered By - A Sarshar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.