0

I am new into Kotlin and trying to learn, how to fetch Data with retrofit and store this data into a Room DB. But as soon as i start the Activity where this process takes place i get a NullPointerException.

EDIT: As far as i could find out now, my "database" in the RoomViewmodel class is still NULL when i want to access it, even though i have an override oncreate function, where it is created

Here is also a link to the GitHub repository from the mini-project I'm working on: https://github.com/Engin92/Dog_Breeds/tree/RoomDatabase

here is my complete errorlist:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.dogbreeds, PID: 14803
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dogbreeds/com.example.Breedlist.activity.DetailedViewActivity}: kotlin.KotlinNullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:213)
        at android.app.ActivityThread.main(ActivityThread.java:8178)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
     Caused by: kotlin.KotlinNullPointerException
        at com.example.Breedlist.activity.DetailedViewActivityRepository.getBreeds(DetailedViewActivityRepository.kt:23)
        at com.example.Breedlist.activity.DetailedViewActivityViewModel.getAllBreedList(DetailedViewActivityViewModel.kt:23)
        at com.example.Breedlist.activity.DetailedViewActivity.onCreate(DetailedViewActivity.kt:42)
        at android.app.Activity.performCreate(Activity.java:8086)
        at android.app.Activity.performCreate(Activity.java:8074)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1313)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3755)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:213) 
        at android.app.ActivityThread.main(ActivityThread.java:8178) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101) 

The important part of DetailedViewActivity

class DetailedViewActivity : AppCompatActivity() {

    lateinit var breedRecyclerView: RecyclerView
    lateinit var detailedViewActivityViewModel: DetailedViewActivityViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_detailed_view)

        breedRecyclerView = findViewById(R.id.breedRecyclerView)

        detailedViewActivityViewModel = ViewModelProviders.of(this).get(
            DetailedViewActivityViewModel::class.java)


        if(isOnline(this))
        {
            detailedViewActivityViewModel.getBreedsFromAPIAndStore()
        }
        else
        {
            Toast.makeText(this,"No internet connection. Showing cached list!",Toast.LENGTH_LONG).show()
        }

        detailedViewActivityViewModel.getAllBreedList().observe(this, Observer<List<CurrentBreedResponseItem>> { breedList ->
            Log.e(MainActivity::class.java.simpleName,breedList.toString())
            setUpBreedRecyclerView(breedList!!)
        })
    } ....

the class RoomViewModel, where i build the DB (where i Think the error is, the var database is still NULL, after trying to access (write/read) it)

class RoomViewModel : Application() {

    companion object {
        var database: BreedDatabase? = null
    }

    override fun onCreate() {
        super.onCreate()
        database =  Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db").fallbackToDestructiveMigration().build()
    }
}

getBreeds function in DetailedViewActivityRepository:

fun getBreeds() : LiveData<List<CurrentBreedResponseItem>>
{
    return RoomViewModel.database!!.currentBreedDao().getAllBreeds()
}

getAllBreedList function in DetailedViewActivityViewModel

fun getAllBreedList(): LiveData<List<CurrentBreedResponseItem>>
{
    return detailedViewActivityRepository.getBreeds()
}
Engin
  • 3
  • 2
  • Hi, I cloned your repository and tried running it. It is working fine and I don't see any crashes. Can you explain exactly when and how it is crashing? – Belal Khan May 23 '20 at 22:37
  • Yes, sure! When I start the app on my mobile phone, i am immediately on the first activity, where I see a list of dog names. As soon as I click on one of the names, the program crashes. Normally the app should have to save the data via an API into my database and display it in the second activity. PS: Did you download the RoomDataBase-branch or the Master? The repository in the RoomDataBase-branch is the one, which doesn't work – Engin May 23 '20 at 23:30
  • Does this answer your question? [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – denvercoder9 May 24 '20 at 00:23
  • You're accessing something that is null here `DetailedViewActivityRepository.kt:23`. And please don't link to a whole repository. It's harder for reviewers to navigate through the whole project which is not necessary at all to provide answers. – denvercoder9 May 24 '20 at 00:26
  • @sonnet as far as i could find out now, my "database" in the RoomViewmodel class is still NULL when i want to access it, even though i have an override oncreate function, where it is created?! – Engin May 24 '20 at 12:24
  • It's null because you did not add your custom application in the [manifest](https://github.com/Engin92/Dog_Breeds/blob/RoomDatabase/app/src/main/AndroidManifest.xml#L8-L13) – denvercoder9 May 24 '20 at 12:29
  • @sonnet yes! That fixed my problem! thanks for the Help :) – Engin May 24 '20 at 14:27
  • Then you should tell about the branch as well. – Belal Khan May 24 '20 at 15:55

1 Answers1

1

There are two problem in your code. The first one is very clear you are trying to access a null object and you are getting NullPointerException. So be careful when you use !! operator.

The reason you are getting it is, inside your RoomViewModel your database instance is null.

class RoomViewModel : Application() {

    companion object {
        var database: BreedDatabase? = null
    }

    override fun onCreate() {
        super.onCreate()
        database = Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db")
            .fallbackToDestructiveMigration().build()
    }
}

You may think you are initializing the database instance in onCreate() but the onCreate() is not getting called. The reason is to make the application class work you need to add it to your AndroidManifest.xml file.

Solution:

Add this RoomViewModel class to your AndroidManifest.xml file like this.

<application
    android:name=".view.RoomViewModel"
    android:allowBackup="true" 

We do it as application tag's name attribute as you can see above. This will fix your null pointer exception. But your program will again crash, because you are using Kotlin and do make room work with kotlin this thing needs to be added in your app level build.gradle file.

kapt "android.arch.persistence.room:compiler:1.1.1"

After adding it to your app level build.gradle inside dependencies block. Sync your project and run it should work.

If you want to learn more about Room Database in Android, you can check this Room Database Tutorial.

Hope this will help you.

Belal Khan
  • 1,784
  • 2
  • 18
  • 29
  • `But your program will again crash, because you are using Kotlin and do make room work with kotlin this thing needs to be added in your app level build.gradle file` OP already had kapt for room in their build.gradle file. That was not a problem. Just adding the application in the manifest is enough as OP confirmed – denvercoder9 May 24 '20 at 17:13
  • In my case it crashed, but no issues as it is working on your side. Cool – Belal Khan May 24 '20 at 17:24
  • i actually had also to change one of my dependencies into kapt to correct all bugs (just forgot to mention it in my comment). Belal was right after all, ty both for your input guys :D – Engin May 24 '20 at 19:04