I'm facing java.io.NotSerializableException when trying to writeObject and object of a data class into an ObjectOutputStream.
Following is the main activity function of my project :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
debug()
}
fun debug() {
val oos = ObjectOutputStream(ByteArrayOutputStream())
val obj = BaseElement("HELLO WORLD")
try{
oos.writeObject(obj)
}
catch(e : Exception) {
Log.d("mydebug", e.stackTraceToString())
}
}
}
The BaseElement class can be found here :
import kotlinx.serialization.Serializable
#Serializable
data class BaseElement(var sentence : String)
The stacktracke is as following :
java.io.NotSerializableException: com.example.myproject.model.BaseElement
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
at com.example.myproject.MainActivity.debug(MainActivity.kt:29)
at com.example.myproject.MainActivity.onCreate(MainActivity.kt:17)
at android.app.Activity.performCreate(Activity.java:8130)
at android.app.Activity.performCreate(Activity.java:8110)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1343)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3781)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3977)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:109)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2374)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:233)
at android.os.Looper.loop(Looper.java:344)
at android.app.ActivityThread.main(ActivityThread.java:8248)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)
Someone please help me understand the solution to this issue.
Implement the serializable interface
import kotlinx.serialization.Serializable
data class BaseElement(var sentence : String) : Serializable
Related
I created a navigation system to navigate to correct fragment based on Destination object which I send with Intent as Parcelable extra
#Serializable
sealed class Destination : Parcelable {
abstract val destinationType: Type
abstract val destinationFragment: Fragment
enum class Type(val defaultDestination: Destination) {
DASHBOARD(Dashboard),
GRADE(Grade),
ATTENDANCE(Attendance),
EXAM(Exam),
TIMETABLE(Timetable()),
HOMEWORK(Homework),
NOTE(Note),
CONFERENCE(Conference),
SCHOOL_ANNOUNCEMENT(SchoolAnnouncement),
SCHOOL(School),
LUCKY_NUMBER(More),
MORE(More),
MESSAGE(Message);
}
#Parcelize
#Serializable
object Dashboard : Destination() {
override val destinationType get() = Type.DASHBOARD
override val destinationFragment get() = DashboardFragment.newInstance()
}
#Parcelize
#Serializable
object Grade : Destination() {
override val destinationType get() = Type.GRADE
override val destinationFragment get() = GradeFragment.newInstance()
}
#Parcelize
#Serializable
object Attendance : Destination() {
override val destinationType get() = Type.ATTENDANCE
override val destinationFragment get() = AttendanceFragment.newInstance()
}
#Parcelize
#Serializable
object Exam : Destination() {
override val destinationType get() = Type.EXAM
override val destinationFragment get() = ExamFragment.newInstance()
}
#Parcelize
#Serializable
data class Timetable(
#Serializable(with = LocalDateSerializer::class)
private val date: LocalDate? = null
) : Destination() {
override val destinationType get() = Type.TIMETABLE
override val destinationFragment get() = TimetableFragment.newInstance(date)
}
#Parcelize
#Serializable
object Homework : Destination() {
override val destinationType get() = Type.HOMEWORK
override val destinationFragment get() = HomeworkFragment.newInstance()
}
#Parcelize
#Serializable
object Note : Destination() {
override val destinationType get() = Type.NOTE
override val destinationFragment get() = NoteFragment.newInstance()
}
#Parcelize
#Serializable
object Conference : Destination() {
override val destinationType get() = Type.CONFERENCE
override val destinationFragment get() = ConferenceFragment.newInstance()
}
#Parcelize
#Serializable
object SchoolAnnouncement : Destination() {
override val destinationType get() = Type.SCHOOL_ANNOUNCEMENT
override val destinationFragment get() = SchoolAnnouncementFragment.newInstance()
}
#Parcelize
#Serializable
object School : Destination() {
override val destinationType get() = Type.SCHOOL
override val destinationFragment get() = SchoolFragment.newInstance()
}
#Parcelize
#Serializable
object LuckyNumber : Destination() {
override val destinationType get() = Type.LUCKY_NUMBER
override val destinationFragment get() = LuckyNumberFragment.newInstance()
}
#Parcelize
#Serializable
object More : Destination() {
override val destinationType get() = Type.MORE
override val destinationFragment get() = MoreFragment.newInstance()
}
#Parcelize
#Serializable
object Message : Destination() {
override val destinationType get() = Type.MESSAGE
override val destinationFragment get() = MessageFragment.newInstance()
}
}
This works perfectly on my devices. I released an app to the Google Play store. I noticed later in Firebase that a small part of users have this error
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{io.github.wulkanowy/io.github.wulkanowy.ui.modules.splash.SplashActivity}: java.lang.RuntimeException: Parcelable encountered IOException reading a Serializable object (name = io.github.wulkanowy.ui.modules.Destination$Exam)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3477)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3620)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2183)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7604)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by java.lang.RuntimeException: Parcelable encountered IOException reading a Serializable object (name = io.github.wulkanowy.ui.modules.Destination$Exam)
at android.os.Parcel.readSerializable(Parcel.java:3136)
at android.os.Parcel.readValue(Parcel.java:2917)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3244)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:292)
at android.os.BaseBundle.unparcel(BaseBundle.java:236)
at android.os.Bundle.getBundle(Bundle.java:924)
at com.google.firebase.messaging.FcmLifecycleCallbacks.logNotificationOpen(FcmLifecycleCallbacks.java:79)
at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:49)
at android.app.Application.dispatchActivityCreated(Application.java:373)
at android.app.Activity.dispatchActivityCreated(Activity.java:1206)
at android.app.Activity.onCreate(Activity.java:1479)
at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:85)
at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:321)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:249)
at io.github.wulkanowy.ui.base.BaseActivity.onCreate(BaseActivity.kt:38)
at io.github.wulkanowy.ui.modules.splash.SplashActivity.onCreate(SplashActivity.kt:44)
at android.app.Activity.performCreate(Activity.java:7822)
at android.app.Activity.performCreate(Activity.java:7811)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1328)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3452)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3620)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2183)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7604)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Caused by java.io.InvalidClassException: io.github.wulkanowy.ui.modules.Destination$Exam; class invalid for deserialization
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:154)
at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:798)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1873)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1412)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)
at android.os.Parcel.readSerializable(Parcel.java:3134)
at android.os.Parcel.readValue(Parcel.java:2917)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3244)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:292)
at android.os.BaseBundle.unparcel(BaseBundle.java:236)
at android.os.Bundle.getBundle(Bundle.java:924)
at com.google.firebase.messaging.FcmLifecycleCallbacks.logNotificationOpen(FcmLifecycleCallbacks.java:79)
at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:49)
at android.app.Application.dispatchActivityCreated(Application.java:373)
at android.app.Activity.dispatchActivityCreated(Activity.java:1206)
at android.app.Activity.onCreate(Activity.java:1479)
at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:85)
at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:321)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:249)
at io.github.wulkanowy.ui.base.BaseActivity.onCreate(BaseActivity.kt:38)
at io.github.wulkanowy.ui.modules.splash.SplashActivity.onCreate(SplashActivity.kt:44)
at android.app.Activity.performCreate(Activity.java:7822)
at android.app.Activity.performCreate(Activity.java:7811)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1328)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3452)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3620)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2183)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7604)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
I can't reproduce this error on my devices or on android emulator.
Link to the app's github repository
https://github.com/wulkanowy/wulkanowy
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Why am I getting getApplicationcontext() null?
(4 answers)
Closed 1 year ago.
So I was learning Manual Dependency Injection from the Android Developers documentation to implement a simple saving mechanism using the Room database library. However, it has been causing the NullPointerException in the Container class:
2021-03-15 07:12:08.370 23721-23721/com.arpansircar.Practice.dependencyinjectionpractice E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.arpansircar.Practice.dependencyinjectionpractice, PID: 23721
java.lang.RuntimeException: Unable to instantiate application com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.app.LoadedApk.makeApplication(LoadedApk.java:1230)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6583)
at android.app.ActivityThread.access$1400(ActivityThread.java:227)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1890)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
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:128)
at com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication.<init>(MyApplication.kt:7)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateApplication(AppComponentFactory.java:76)
at androidx.core.app.CoreComponentFactory.instantiateApplication(CoreComponentFactory.java:52)
at android.app.Instrumentation.newApplication(Instrumentation.java:1156)
at android.app.LoadedApk.makeApplication(LoadedApk.java:1222)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6583)
at android.app.ActivityThread.access$1400(ActivityThread.java:227)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1890)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Here are the classes where I figure there could be an error.
AppContainer.kt
package com.arpansircar.practice.dependencyinjectionpractice.di
import android.content.Context
import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository
import com.arpansircar.practice.dependencyinjectionpractice.room.UserDao
import com.arpansircar.practice.dependencyinjectionpractice.room.UserDatabase
import com.arpansircar.practice.dependencyinjectionpractice.viewmodel.UserViewModelFactory
class AppContainer(context: Context) {
private val userDao: UserDao = UserDatabase.getInstance(context).userDao()
private val userRepository: UserRepository = UserRepository(userDao)
val userViewModelFactory: UserViewModelFactory = UserViewModelFactory(userRepository)
}
MyApplication.kt
package com.arpansircar.practice.dependencyinjectionpractice.di
import android.app.Application
class MyApplication : Application() {
val appContainer = AppContainer(applicationContext)
}
MainActivity.kt
package com.arpansircar.practice.dependencyinjectionpractice.view
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import com.arpansircar.practice.dependencyinjectionpractice.di.AppContainer
import com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication
import com.arpansircar.practice.dependencyinjectionpractice.R
class MainActivity : AppCompatActivity() {
private var appContainer: AppContainer? = null
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
appContainer = (application as MyApplication).appContainer
val navHostFragment: NavHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment_container) as NavHostFragment
navController = navHostFragment.findNavController()
}
override fun onDestroy() {
super.onDestroy()
appContainer = null
}
}
RegistrationFragment.kt
package com.arpansircar.practice.dependencyinjectionpractice.view
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.arpansircar.practice.dependencyinjectionpractice.databinding.FragmentRegistrationBinding
import com.arpansircar.practice.dependencyinjectionpractice.di.MyApplication
import com.arpansircar.practice.dependencyinjectionpractice.room.UserEntity
import com.arpansircar.practice.dependencyinjectionpractice.viewmodel.UserViewModel
class RegistrationFragment : Fragment(), View.OnClickListener {
private lateinit var binding: FragmentRegistrationBinding
private lateinit var userViewModel: UserViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val appContainer = (context as MyApplication).appContainer
userViewModel = ViewModelProvider(
this,
appContainer.userViewModelFactory
).get(UserViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentRegistrationBinding.inflate(
inflater,
container,
false
)
return binding.root
}
override fun onStart() {
super.onStart()
binding.createAccountButton.setOnClickListener(this)
binding.getAllAccountsButton.setOnClickListener(this)
}
override fun onClick(view: View?) {
when (view) {
binding.createAccountButton -> {
val name: String = binding.userNameTextInputEditText.text.toString()
val userName: String = binding.userUsernameTextInputEditText.text.toString()
val password: String = binding.userPasswordTextInputEditText.text.toString()
val userEntity = UserEntity(0, name, userName, password)
userViewModel.insertUsers(userEntity)
}
binding.getAllAccountsButton -> {
}
}
}
}
UserViewModelFactory.kt
package com.arpansircar.practice.dependencyinjectionpractice.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository
class UserViewModelFactory(private val userRepository: UserRepository) : ViewModelProvider.Factory {
#Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
return UserViewModel(userRepository) as T
}
throw IllegalArgumentException("Unknown ViewModel Class")
}
}
UserViewModel.kt
package com.arpansircar.practice.dependencyinjectionpractice.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.arpansircar.practice.dependencyinjectionpractice.repository.UserRepository
import com.arpansircar.practice.dependencyinjectionpractice.room.UserEntity
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
class UserViewModel(private val userRepository: UserRepository) : ViewModel() {
fun insertUsers(userEntity: UserEntity) {
viewModelScope.launch(IO) {
userRepository.insertUser(userEntity)
}
}
fun getUsers(): LiveData<List<UserEntity>> {
return userRepository.selectUsers()
}
}
Specifically, the error points to line no. 7 in the MyApplication.kt class
val appContainer = AppContainer(applicationContext)
stating
Attempt to invoke virtual method
'android.content.Contextandroid.content.Context.getApplicationContext()'
on a null object reference
I can't figure out how the context can be null considering that I'm invoking the MyApplication class in the onCreate method of my MainActivity.kt class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
appContainer = (application as MyApplication).appContainer
...
}
and in the onCreate method of my RegistrationFragment.kt class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val appContainer = (context as MyApplication).appContainer
userViewModel = ViewModelProvider(
this,
appContainer.userViewModelFactory
).get(UserViewModel::class.java)
}
I mean, shouldn't the activity and fragment been started and initialized with a context within these methods?
class MyApplication : Application() {
val appContainer = AppContainer(applicationContext)
}
You're trying to use your Application as a Context too early, at init phase before it is fully set up.
In theory the Application here is the application context, so you could replace applicationContext with this but that would only move the same issue to your AppContainer where you're trying to use the Context at init phase.
Consider postponing the usage of Context. For example, you could wrap your appContainer in a lazy delegate that inits AppContainer on first access and not at init phase.
applicationContext will be null until the Application onCreate();
Fisrt , you could try code below:
class MyApplication : Application() {
var appContainer: Context? = null
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
Log.d("TAG", "attachBaseContext: " + applicationContext)
}
override fun onCreate() {
super.onCreate()
Log.d("TAG", "onCreate: " + applicationContext)
}
}
could get log:
D/TAG: attachBaseContext: null
D/TAG: onCreate: siger.kotest0.MyApplication#6d46e8e
So you could use applicationContext in onCreate():
var appContainer: Context? = null
override fun onCreate() {
super.onCreate()
appContainer = AppContainer(base)
Log.d("TAG", "onCreate: " + applicationContext)
}
}
I have a problem with View Model. In activity "Analysis" I had to break something in the code, and I can't find the error. Can somebody help me. I'm a newbie in the Android program and I often make stupid mistakes. I will try to find the error by then.
Thanks so much for your help
Regards
DAO
package com.example.mwproto1.ROOM
import androidx.lifecycle.LiveData
import androidx.room.*
#Dao
interface PomiarDao {
#Insert
suspend fun addPomiar(pomiar: Pomiar)
#Query("SELECT * FROM pomiar ORDER BY id DESC")
suspend fun getAllPomiar():List<Pomiar>
#Insert
suspend fun addMultiplePomiar(vararg pomiar: Pomiar)
#Update
suspend fun updatePomiar(pomiar: Pomiar)
#Delete
suspend fun deletePomiar(pomiar: Pomiar )
#Query("SELECT avg(Stezenie) FROM Pomiar ")
fun average(): LiveData<Float>
}
REPOSITORY
package com.example.mwproto1.ROOM
import android.app.Application
import androidx.lifecycle.LiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
class Repository(application: Application) {
private var pomiardao: PomiarDao
init {
val database = Database
.buildDatabase(application.applicationContext)
pomiardao = database.getPomiarDao()
}
fun averageasync(): Deferred<LiveData<Float>> =
CoroutineScope(Dispatchers.IO).async {
pomiardao.average()
}
}
ViewModel
package com.example.mwproto1.ViewModel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import com.example.mwproto1.ROOM.Pomiar
import com.example.mwproto1.ROOM.Repository
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.runBlocking
class ViewModel(application: Application):AndroidViewModel(application) {
private var PomiarRepository: Repository = Repository(application)
private var allpomiar: Deferred<LiveData<Float>> =
PomiarRepository.averageasync()
fun AverageVM(): LiveData<Float> = runBlocking {
allpomiar.await()
}
}
Entity
package com.example.mwproto1.ROOM
import android.os.Parcel
import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity
data class Pomiar(
#ColumnInfo(name="Stezenie")
val Stezenie: String?,
#ColumnInfo(name="Data")
val Data: String?,
#ColumnInfo(name="Zegar")
val Zegar: String?,
#ColumnInfo(name="Posilek")
val Posilek: String?,
#ColumnInfo(name="Samopoczucie")
val Samopoczucie: String?,
#ColumnInfo(name="Stres")
val Stres: String?,
#ColumnInfo(name="Hiperglikemia")
val Hiperglikemia: String?
): Parcelable{
#PrimaryKey(autoGenerate = true)
var id :Int = 0
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString()
) {
id = parcel.readInt()
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(Stezenie)
parcel.writeString(Data)
parcel.writeString(Zegar)
parcel.writeString(Posilek)
parcel.writeString(Samopoczucie)
parcel.writeString(Stres)
parcel.writeString(Hiperglikemia)
parcel.writeInt(id)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Pomiar> {
override fun createFromParcel(parcel: Parcel): Pomiar {
return Pomiar(parcel)
}
override fun newArray(size: Int): Array<Pomiar?> {
return arrayOfNulls(size)
}
}
}
ANALIZA-ACTIVITY
package com.example.mwproto1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.example.mwproto1.ROOM.Pomiar
import com.example.mwproto1.UI.PomiarAdapter
import kotlinx.android.synthetic.main.activity_analiza.*
import kotlin.properties.Delegates
public class Analiza : AppCompatActivity() {
private lateinit var textView: TextView
private lateinit var viewModel: ViewModel
private lateinit var daoAdapter:PomiarAdapter
private lateinit var pomiar: LiveData<Float>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_analiza)
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(application)
.create(ViewModel::class.java)
textView = findViewById(R.id.TV7)
pomiar.observe(this,Observer {
textView.setText(it.toString()) })
}
}
ERROR
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mwproto1, PID: 11239
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mwproto1/com.example.mwproto1.Analiza}:
kotlin.UninitializedPropertyAccessException: lateinit property pomiar
has not been initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property pomiar has not been initialized
at com.example.mwproto1.Analiza.onCreate(Analiza.kt:34)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
I/Process: Sending signal. PID: 11239 SIG: 9 Disconnected from the
target VM, address: 'localhost:8603', transport: 'socket'
Just like the error said: " lateinit property pomiar has not been initialized"
You probably want to add:
pomiar = viewModel.AverageVM() after you initialize viewModel in ANALIZA-ACTIVITY
I am making an app where each user can add to his Todo List, I have a problem with folder paths.
this is the part of reading data code was adding "child(auth.currentUser?.uid!!)" makes everything crash. without it though it works but shows information of all users with dictionary form.
db.child(auth.currentUser?.uid!!).addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
println("The read failed")
}
override fun onDataChange(p0: DataSnapshot) {
for (i in p0.children) {
val notToDo: String = i.value.toString()
notToDos.add(notToDo)
}
listView = findViewById(R.id.listview)
listView.adapter = ArrayAdapter<String>(
this#ToDoActivity,
R.layout.listview,
notToDos
)
}
})
This is the whole code, but neither the adding part works
package ge.msda.firebaseauth
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import android.widget.Toast
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import kotlinx.android.synthetic.main.activity_to_do.*
class ToDoActivity : AppCompatActivity() {
private lateinit var db: DatabaseReference
lateinit var listView: ListView
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_to_do)
db = FirebaseDatabase.getInstance().getReference("UserInfo")
val notToDos = arrayListOf<String>()
TodoSubmit.setOnClickListener {
val text = TodoText.text.toString()
db.child(auth.currentUser?.uid!!).child("ToDos").push().setValue(text).addOnCompleteListener {
if(it.isSuccessful()){
Toast.makeText(this, "Success", Toast.LENGTH_LONG).show()
}
else {
Toast.makeText(this, it.exception.toString(), Toast.LENGTH_LONG).show() }
}
TodoText.setText("")
notToDos.clear()
}
db.child(auth.currentUser?.uid!!).addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
println("The read failed")
}
override fun onDataChange(p0: DataSnapshot) {
for (i in p0.children) {
val notToDo: String = i.value.toString()
notToDos.add(notToDo)
}
listView = findViewById(R.id.listview)
listView.adapter = ArrayAdapter<String>(
this#ToDoActivity,
R.layout.listview,
notToDos
)
}
})
}
}
error tracktrace
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ge.msda.firebaseauth, PID: 11939
java.lang.RuntimeException: Unable to start activity ComponentInfo{ge.msda.firebaseauth/ge.msda.firebaseauth.ToDoActivity}: kotlin.UninitializedPropertyAccessException: lateinit property auth has not been initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property auth has not been initialized
at ge.msda.firebaseauth.ToDoActivity.onCreate(ToDoActivity.kt:41)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
This is the way the database looks like and I want to add a new folder in each user named "ToDos" where I can add other items.
You are getting that error because you forgot to initialize your auth object. To solve this, simply add the following line of code:
auth = FirebaseAuth.getInstance()
Right after the following line of code:
db = FirebaseDatabase.getInstance().getReference("UserInfo")
I am new to android Kotlin. I am trying to Pass object from one activity to another activity I got stuck,
MyClass :
data class MyPojo(val name: String, val age: String) : Serializable
FirstActivity :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editTextName = findViewById<EditText>(R.id.EditName)
val editTextAge = findViewById<EditText>(R.id.EditAge)
val button = findViewById<Button>(R.id.ButtonSend)
button.setOnClickListener {
val object1 = MyPojo(editTextName.text.toString(),editTextAge.text.toString())
val intent = Intent(this,Main2Activity::class.java)
intent.putExtra("Obj",object1)
startActivity(intent)
}
}
}
SecondActivity :
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val obj :MyPojo = intent.getSerializableExtra("obj") as MyPojo
val textView : TextView = findViewById(R.id.textViewName)
val textViewAge : TextView = findViewById(R.id.textViewAge)
textView.setText(obj.name)
textViewAge.setText(obj.age)
}
}
Error :
6-28 19:35:58.625
22192-22192/com.example.evalai.passingobjecttoactivity
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.evalai.passingobjecttoactivity, PID: 22192
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.evalai.passingobjecttoactivity/com.example.evalai.passingobjecttoactivity.Main2Activity}:
kotlin.TypeCastException: null cannot be cast to non-null type
com.example.evalai.passingobjecttoactivity.MyPojo
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
at android.app.ActivityThread.access$800(ActivityThread.java:156)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:211)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)
Caused by: kotlin.TypeCastException: null cannot be cast to non-null type com.example.evalai.passingobjecttoactivity.MyPojo
at com.example.evalai.passingobjecttoactivity.Main2Activity.onCreate(Main2Activity.kt:14)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
The key you are providing for storing your pojo into the Intent is not the same key you are using to read it (you are storing with "Obj" and reading with "obj").
When you read the intent in your Main2Activity, there is nothing stored with that key, so you return null. And, obviously, you can't cast null to MyPojo.
To avoid these problems, you should always declare a constant for the keys of your intents:
const val ARG_POJO = "argPojo"
And use it to store and read from them:
Store:
intent.putExtra(ARG_POJO, object1)
Read:
val obj: MyPojo = intent.getSerializableExtra(ARG_POJO) as MyPojo
Step 1: Make your data class serializable
data class MyPojo(val name: String, val age: String) : Serializable
Step 2: From Sending Activity
val object1 = MyPojo(editTextName.text.toString(),editTextAge.text.toString())
val intent = Intent(this,Main2Activity::class.java)
intent.putExtra("Obj",object1 as Serializable)
startActivity(intent)
Step 3: At receiving activity
val receivedObject:MyPojo=intent?.getSerializableExtra(Obj) as MyPojo
That's it.