Uninitialized exception while initializing "late init" property - android

I am not really sure if my case is just not possible with late init properties. But let me just ask :)
I have an applicationController which is used in nearly every activity - so i created a BaseActivity
The problem now is that when I want to get dependencies from the application controller in the child activity, I get an Uninitialized Exception.
Thanks for your help!

Because you override wrong method in BaseActivity, that why your app crash.
Solution: Change your code to
abstract class BaseActivity : AppCompatActivity() {
lateinit var applicationController: ApplicationController
// [IMPORTANT] Remove or comment-out this method
// override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
// super.onCreate(savedInstanceState, persistentState)
// applicationController = ApplicationController.getInstance(applicationContext)
// }
// Override this method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
applicationController = ApplicationController.getInstance(applicationContext)
}
}
Explanation: This section will explain why the code is not working.
kotlin.UninitializedPropertyAccessException
This is a sub-class of RuntimeException, the app will throw this
exception when you access an object by calling properties or methods
on its own before initializing.
When LoginScreen activity is created, Android will call its onCreate method.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login_screen)
emailMatcher = applicationController.getEmailMatcher()
passwordMatcher = applicationController.getPasswordMatcher()
}
The first line super.onCreate(savedInstanceState) will call onCreate method of its parent, in this case onCreate (bundle) in BaseActivity activity will be called.
Unfortunately, in BaseActivity activity, you override and put the initial code for applicationController in another method onCreate(bundle, persistentState) which quite similar to onCreate (bundle). The difference between them is number of params. As a result, at this time applicationController is still not initialized.
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
applicationController = ApplicationController.getInstance(applicationContext)
}
Until the app reach this line
emailMatcher = applicationController.getEmailMatcher()
Because you call getEmailMatcher method on an uninitialized object applicationController, so the app throws kotlin.UninitializedPropertyAccessException and make your app crash.

Related

Function onCreate not execute on activity start Kotlin Android

I'm new to Android development and I just started learning.
Here's my problem:
My onCreate function in activity_main works normally, it shows everything. Then he logs in and shows me the second activity and there also the onCreate function works but when I go to the third activity the onCreate function does not execute.
DashboardActivity.kt
class DashboardActivity : AppCompatActivity() {
#SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
val policy = ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy)
sendGet()
// sendPostRequest()
}
fun openTest(view: View){
setContentView(R.layout.activity_test);
}
}
TestActivity.kt
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
println("test")
}
}
Could someone guide me or explain what and how? I've been sitting on this for a while, searching the internet and nothing...
I searched the internet, tried solutions, tried to create more activities, turned on debug mode by adding breakpoint and it doesn't even enter this function
To start an Activity, you need to call the following:
startActivity(Intent(this, NextActivity::class.java))
Otherwise, onCreate(Bundle?) will not be called if you do not explicitly call the above.
So in your case, seems that you would like to get to TestActivity in openTest(View), you should have something like this:
fun openTest(view: View) {
startActivity(Intent(this, TestActivity::class.java))
// Calling setContentView() will not trigger another Activity
// setContentView(R.layout.activity_test);
}

Where can I put Kotlin code I want to run on app startup when using flutter?

I have some initialisation kotlin code I want to run when my flutter app starts.
My app already has a MainActivity.kt that exists in app/src/main/kotlin/com/example/my_app/
I then added an onCreate to this activity and added an exception to confirm this code executed....but it did not...
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
throw RuntimeException("blah");
}
}
Where can I put kotlin initialization code that I want to execute on application launch?
You use a different oncreate method android first calls this method while loading android app it is lifecycle method.
class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
throw RuntimeException("blah");
}
}

How to execute the same function in the onCreate method of all activities?

What is the problem?
I want to add this custom window callback in each activity already implemented in the app, currently I need to manually modify the code of the onCreate method of each activity or make it inherit a class that already has onCreate in the desired way, but I need that this process could be performed without modifying the app's existing code, just adding some initialization.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.callback = CustomCallback(window.callback, this)
}
Inside you app Application Class (you'll need to create one, if not done yet), on "onCreate" method, call
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
//Code here will run for every activity
}
}
You need a BaseActivity
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//your code
}
All of your activities need to extends BaseActivity
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}

How to pass data from onCreate() to onSaveInstanceState()?

I have an onCreate() function and an onSaveInstanceState() function in my Main Activity. I have declared a Map in my onCreate() and I want to access the keys of that Map in my onSaveInstanceState() function, so as to save them to the outState bundle.
class MainActivity: AppCombatActivity(){
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
//Want to access the iconMap here, but it is outside of the Map's scope. How do I access it?
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val iconMap = mapOf("contactlessIcon" to getDrawable(R.drawable.ic_contactless_24px), "fingerprintIcon" to getDrawable(R.drawable.ic_fingerprint_black_48dp), "codeIcon" to getDrawable(R.drawable.ic_code_24px))
}
}
I'm fairly new to Android programming, so this might be an easy fix. I want to access the iconMap in the onSaveInstanceState() but it is outside iconMap's scope. I cannot make iconMap a global variable, for this crashes my app.
As #ianhanniballake commented - you shouldn't be saving Drawables that are always the same. In this case it's especially unnecessary since you're onCreate will be called again whenever the activity is restored.
But, to answer your question, you can do it like this :
class MainActivity: AppCombatActivity(){
// define it here, so it's a member of the class
lateinit val iconMap: Map<String, Drawable>
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
//now you can use it here
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//set its value
iconMap = mapOf("contactlessIcon" to getDrawable(R.drawable.ic_contactless_24px), "fingerprintIcon" to getDrawable(R.drawable.ic_fingerprint_black_48dp), "codeIcon" to getDrawable(R.drawable.ic_code_24px))
}
}

startActivity skips onCreate()

I have a simple case of Activity1 -> Activity2.
In the past when I've used startActivity(Intent(this, Activity2::class.java)) there have been no issues and the onCreate() method of Activity2 would be called.
In my current case this is not happening. I have logs in the onCreate() method and they are never hit. But if I create a onStart() method it enters there. However, never in my logs for the lifetime of the application does onCreate() of Activity2 ever get hit. How is this possible. onCreate is a requirement before onStart I thought.
Here is the actual code I'm referencing above.
class Activity1 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.d("onCreate")
setContentView(R.layout.activity_splash)
startActivity(Activity2.getIntent(this))
}
}
class Activity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
Timber.d("onCreate") // Never gets touched
}
override fun onStart() {
super.onStart()
Timber.d("onStart"); // Is hit with no problems.
}
companion object {
fun getIntent(#NonNull context: Context) : Intent {
return Intent(context, Activity2::class.java)
}
}
}
You overrode the wrong onCreate - you do not want to use the PersistableBundle version. Change your onCreate to only take the savedInstanceState: Bundle? parameter:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.d("onCreate") // Now it'll be called
}

Categories

Resources