I am studying with Kotlin and I have not been able to solve the error for several days, so I am asking for help.
I am trying to retrieve data from the room database and put it into a variable(productlist), but an error occurs as follows.
kotlin.UninitializedPropertyAccessException: lateinit property productList has not been initialized
Here is my source codes. I already checked that the room database contains data normally.
I want to put data fetched from db in productList variable and use it.
Thanks in advance!
[MainActivity.kt]
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var PACKAGE_NAME: String
private var currentPosition: Int = 0
private var lastPosition: Int = 0
private lateinit var db: AppDatabase
private lateinit var productDao: ProductDao
private lateinit var productList: List<ProductEntity>
private var urls: String = ""
private var titles: String = ""
private var descs: String = ""
private var isVideos: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)!!
productDao = db.getProductDao()
setVideoItem()
}
private fun setVideoItem() {
val videosViewPager = binding.viewPagerVideos
val videoItems: MutableList<VideoItem> = ArrayList()
val files = File([email protected], "products").listFiles()
Thread {
productList = productDao.getAll()
}.start()
for (i in productList) { //I want to store accessed data to productList variable
urls = "${i.idx}:"
titles = "${i.name}:"
descs = "${i.price}:"
}
println("urls:$urls")
println("titles:$titles")
println("descs:$descs")
}
[ProductDao.kt]
@Dao
interface ProductDao {
@Query("select * from ProductEntity")
fun getAll() : List<ProductEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(product: ProductEntity)
@Query("select idx, name, price from ProductEntity where idx like :searchIdx")
fun searchProductByIdx(searchIdx: String) : ProductEntity
}
CodePudding user response:
productDao.getAll()
is called on a separate thread which takes time to execute. So you're trying to access productList
before the thread initializes it.
It's race condition in which the thread always loses.
Relocating the code that uses productList
to the thread should solve this race:
Thread {
productList = productDao.getAll()
for (i in productList) {
urls = "${i.idx}:"
titles = "${i.name}:"
descs = "${i.price}:"
}
println("urls:$urls")
println("titles:$titles")
println("descs:$descs")
}.start()
CodePudding user response:
Thread {
productList = productDao.getAll()
}.start()
Product list is being fetched in a thread in a parallel process so since it is not synchronous when the control is on the line for (i in productList)
according to the program the product list has not been initialized.. You have to decide how you handle this concurrency. either call the method synchronously or populate the list after iteration via some method or do it in the same thread .
Something like
Thread {
productList = productDao.getAll()
//iterate through the list
//print the values
}.start()
CodePudding user response:
Start a thread to access db,it will take some time.The main thread will not wait for the thread accessing the database to complete, so it is uninitialized to read productList at this time.
You can access the list after loading is complete, or use Android Handler
to notify the main thread of the update after loading is complete.
Thread {
productList = productDao.getAll()
for (i in productList) {
urls = "${i.idx}:"
titles = "${i.name}:"
descs = "${i.price}:"
}
println("urls:$urls")
println("titles:$titles")
println("descs:$descs")
}.start()