1

I'm trying to call my database (made with Room) from an activity on Android, but it needs the application context, and if I passed "application : Application" in the constructor of my Activity, the build crash and tell me :

java.lang.Class<com.exemple.instabus.PhotoActivity> has no zero argument constructor

Here is my code :

class PhotoActivity(application: Application) : AppCompatActivity() {


    private val pictureDao = PictureDatabase.getDatabase(app)

//Some code ....

I need a context, i've tried to pass "this" but i got another error

Can someone give me some help please, I'm a beginner in this technology

EDIT:

Here is my database class, just to show you why I need an Application Context


@Database(entities = [Picture::class], version = 1, exportSchema = false)
abstract class PictureDatabase : RoomDatabase(){

    abstract fun pictureDao() : PictureDao

     companion object{
        @Volatile
        private var INSTANCE : PictureDatabase? = null

        fun getDatabase(context: Context): PictureDatabase {
            if(INSTANCE == null){
                synchronized(this){
                    INSTANCE = Room.databaseBuilder(
                            context.applicationContext,
                            PictureDatabase::class.java,
                            "pictures.db"
                    ).build()
                }
            }
            return INSTANCE!!
        }
    }

}
Ferenc
  • 39
  • 7
  • 1
    https://stackoverflow.com/questions/5018545/getapplication-vs-getapplicationcontext – Reza Jan 29 '21 at 18:51
  • Thank you @Reza for this link to another question, I learn something, but not enough to solve my problem.. – Ferenc Jan 29 '21 at 19:09
  • 1
    well my friend remove application: Application from activity consructor. usually activities and fragments should have empty constructor because android instantiates them for us and we are not responsible for creating them – Reza Jan 29 '21 at 19:31

3 Answers3

1

First create a ViewModel, and inside the ViewModel you can access the your Dao, pictureDao.

 class PictureViewModel(application: Application) : 
   AndroidViewModel(application) {


     val pictureDao: PictureDao

     init {
         pictureDao = 
        PictureDatabase.getDatabase(application).pictureDao()
   
         }



      }

Then in your activity, initialize the ViewModel. And access your Dao.

 class PhotoActivity : AppCompatActivity() {

   private lateinit var pictureViewModel: PictureViewModel

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

    pictureViewModel = 
   ViewModelProviders.of(this).get(PictureViewModel::class.java)

   //You can now access your Dao class here:
   val pictureDao = pictureViewModel.pictureDao




    
 }
 }
1

Activity is something we do declare in the manifest and then start them using intent, However, the creation of an instance of an activity is done by the system and not by us. An instance is created using constructor, but if it is us then we can have any number of overloaded constructors. But the system needs only one constructor which should be a zero parameter constructor and it should be public.

So your activity signature

class PhotoActivity(application: Application) : AppCompatActivity() {

should be changed to

class PhotoActivity() : AppCompatActivity() {

To call the fun getDatabase(context: Context): PictureDatabase you can pass this from the activity. Activity is an indirect child of Context.

You can do it in the following ways,

  1. private val pictureDao by lazy{ PictureDatabase.getDatabase(this) }
  2. private lateinit var pictureDao:PictureDatabase then in onCreate() initialize it
final override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.your_layout)
        PictureDatabase.getDatabase(this)
        //your logic goes here
   }
rahat
  • 1,840
  • 11
  • 24
0

You should not pass Application to the constructor. You should pass applicationContext to getDatabase(), like private val pictureDao = PictureDatabase.getDatabase(applicationContext)

Sergei Mikhailovskii
  • 2,100
  • 2
  • 21
  • 43