dazai
dazai

Reputation: 716

System services not available to Activities before onCreate() : ROOM

I have this activity in which I have this callback for when an image is clicked. It was working fine but now I added that if it is clicked then it saves the data on the database. The thing is, now I get the system services not available error and I am not sure how to fix it. Any ideas?

This is the activity (I'm only showing the relevant parts of it):

class MainActivity : AppCompatActivity(), RecyclerAdapter.Callback, androidx.appcompat.widget.SearchView.OnQueryTextListener {
   private lateinit var binding: ActivityMainBinding
   private val movies = mutableListOf<Movie>()
   private lateinit var adapter: RecyclerAdapter
   private lateinit var progressBar: ProgressBar
   private lateinit var mMoviesViewModel: MoviesViewModel

   private val viewModel: MainViewModel by viewModels(
       factoryProducer = { MainViewModelFactory() }
   )

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       binding = ActivityMainBinding.inflate(layoutInflater)
       setContentView(binding.root)
       binding.svSearch.setOnQueryTextListener(this)
       //setup progress bar
       progressBar = binding.ProgressBar
       progressBar.visibility = View.VISIBLE

       setObservers()
       initRecyclerView()


   }

private fun initRecyclerView() {
       adapter = RecyclerAdapter(movies)
       binding.rvMovies.layoutManager = GridLayoutManager(this, 3)
       binding.rvMovies.adapter = adapter
       adapter.callback = this
   }

//instantiate database for later
   val db = Room.databaseBuilder(
       this,
       MoviesDatabase::class.java, "database-name"
   ).build()

   val dao = db.moviesDao()


   //send details of clicked movie to fragment
   override fun onMovieClicked(movie: Movie) {
       val transaction = supportFragmentManager
       val detailFragment = DetailFragment()
       val data = Bundle()

       //check if movie is already in database

       if(dao.movieExists(movie.id)){
           //send movie's id to fragment
           data.putString("Title", movie.title)
           detailFragment.arguments = data
       } else {

           val title = movie.title
           val image = movie.poster
           val overview = movie.overview
           val language = movie.originalLanguage
           val releaseDate = movie.releaseDate
           val popularity = movie.popularity
           val voteAverage = movie.voteAverage

           //create movie object
           val movie = Movies(id =0, title, image, overview,
               language, popularity, releaseDate, voteAverage
           )

           //add data to db
           mMoviesViewModel.addMovie(movie)

           //send movie's id to fragment
           data.putString("Title", movie.title)
           detailFragment.arguments = data
       }
       //pass data to fragment
       transaction.beginTransaction()
           .replace(R.id.frag_container, detailFragment)
           .addToBackStack(null)
           .commit()
   }

}

Stack trace:

E/AndroidRuntime: FATAL EXCEPTION: main
   Process: com.app.challengemovieapp.develop, PID: 13142
   java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.app.challengemovieapp.develop/com.app.challengemovieapp.ui.MainActivity}: java.lang.IllegalStateException: System services not available to Activities before onCreate()
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3032)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3269)
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
       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:1960)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7094)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
    Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
       at android.app.Activity.getSystemService(Activity.java:6143)
       at androidx.room.RoomDatabase$JournalMode.resolve(RoomDatabase.java:663)
       at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1346)
       at com.app.challengemovieapp.ui.MainActivity.<init>(MainActivity.kt:129)
       at java.lang.Class.newInstance(Native Method)
       at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
       at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
       at android.app.Instrumentation.newActivity(Instrumentation.java:1219)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3020)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3269) 
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
       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:1960) 
       at android.os.Handler.dispatchMessage(Handler.java:106) 
       at android.os.Looper.loop(Looper.java:214) 
       at android.app.ActivityThread.main(ActivityThread.java:7094) 
       at java.lang.reflect.Method.invoke(Native Method) 
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) 
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975) 

Upvotes: 0

Views: 205

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007554

You will need to move these lines:

   val db = Room.databaseBuilder(
       this,
       MoviesDatabase::class.java, "database-name"
   ).build()

   val dao = db.moviesDao()

Room needs to call methods on Context that are not ready at the point when your MainActivity is being instantiated. You should not try using Room until after super.onCreate() of your onCreate() function.

Upvotes: 1

Related Questions