onCreate in abstract parent activity no called in kotlin - android

I declared a child of MapActivity:
class RecordingActivity : MapActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("RecirdingActivity", "InitializeMap") //called
}
override fun getView(): Int {
return R.layout.activity_recording
}
}
I make a call to start this activity from my main activity:
fab.setOnClickListener {
Log.d("MainActivity", "fabClick") //called
startActivity(intentFor<RecordingActivity>())
}
and I have the abstract activity:
abstract class MapActivity: AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(getView())
initializeMap()
Log.d("MapActivity", "InitializeMap")//not called
}
}
and onCreate method of this activity is never called
I traced it with a debugger and I had the same result.
What am I doing wrong?

there seems to be two solutions:
maybe the onCreate you actually want to override in MapActivity has the signature onCreate(android.os.Bundle):
abstract class MapActivity: AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getView())
initializeMap()
Log.d("MapActivity", "InitializeMap")
}
}
the documentation of the onCreate(android.os.Bundle, android.os.PersistableBundle) method that is being overridden in MapActivity suggests that persistableMode for the activity in the AndroidManifest.xml needs to be set to persistAcrossReboots for it to be called...but MapActivity is abstract, so you would need to set the attribute for its subclasses instead. in this case that would be RecordingActivity.
<?xml version="1.0" encoding="utf-8"?>
<manifest>
...
<application>
...
<activity
android:name=".RecordingActivity"
android:persistableMode="persistAcrossReboots"/>
...
</application>
...
</manifest>

Simple answer: method onCreate(savedInstanceState: Bundle?) and onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) is not the same.
You need to override the same method, probably the first one.

Related

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)
}
}

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
}

Uninitialized exception while initializing "late init" property

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.

Simple Kotlin Project does not show any UI

I have a very simple Android Project in Kotlin. Just to dig in Kodein. I can not see the two TextViews in the main_layout?
I have used MVP pattern for the only MainActivity I have there..
The app starts without a crash and is show a blank white screen.
Any hints?
BaseActivity:
abstract class BaseActivity<V : BasePresenter.View> : AppCompatActivity(), BasePresenter.View {
protected abstract val layoutResourceId : Int
protected abstract val presenter : BasePresenter<V>
val kodeinMu = LazyKodein(appKodein)
protected abstract fun initUI()
protected abstract fun initPresenter()
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(layoutResourceId)
initUI()
initPresenter()
}
override fun onPause() {
super.onPause()
presenter.pause()
}
override fun onStop() {
super.onStop()
presenter.stop()
}
override fun onDestroy() {
super.onDestroy()
presenter.destroy()
}
protected fun toast(s: String) {
System.out.println("TAG $s")
}
}
I have read that it is because of API 28 you only can see on API_28 devices or emulators. Either emulator or on real device were also blanked out.
You override the wrong onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) in you activity:
use this : onCreate(savedInstanceState: Bundle?)

No view found for id 0x7f080035 (com.androidjetpackph:id/container) for fragment PostFragment

I want to create a contract for all the activites to have, for that reason I am creating a base activity, but for some reason the error regarding the R.id.container shows up.
I am doing a Base Activity with the following code:
abstract class BaseActivity : AppCompatActivity() {
#LayoutRes
abstract fun layoutToInflate(): Int
abstract fun doOnCreated()
open fun initialFragment(): Fragment? = null
abstract fun defineInitialFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
doOnCreated()
}
}
This is my MainActivity
class MainActivity : BaseActivity() {
override fun layoutToInflate() = R.layout.activity_main
override fun doOnCreated() {
defineInitialFragment()
}
override fun initialFragment() = PostFragment.newInstance()
override fun defineInitialFragment() {
val initialFragment = initialFragment() ?: return
supportFragmentManager
.beginTransaction()
.replace(R.id.container, initialFragment)
.commitNow()
}
This is my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainActivity" />
</layout>
In your posted code, this is your base onCreate():
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
doOnCreated()
}
And this is your subclass:
override fun doOnCreated() {
defineInitialFragment()
}
In neither of these places do you actually set the activity's content view. You have to call setContentView(layoutToInflate()) somewhere, probably in your base activity's onCreate():
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(layoutToInflate())
doOnCreated()
}

Categories

Resources