Today I opened my project which haven't been updated for about 6 months now and I decided to update all the libraries to make it up to date with recent Android development environment.
After updating a couple of libraries my app throws an exception inside a very simple AsyncTask's onBackground() part.
Here is my AsyncTask, very simple code, creates database in the background, then starts a new activity.
new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
//Creates database while showing a simple loading screen.
MyDatabase.initalize();
return null;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
//When the database has been created, starts a new activity
if (isInForeground) {
Intent intent= new Intent(StartAppActivity.this, GameAppActivity.class);
startActivity(intent);
finish();
}
}
}.execute();
hu.myname.test.app E FATAL EXCEPTION: AsyncTask #1
Process: hu.myname.test.app, PID: 15536
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:415)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.ExceptionInInitializerError
at hu.myname.test.game.dbs.lexicon.MyDatabase.initalize(MyDatabase.java:49)
at hu.myname.test.activity.StartAppActivity$1.doInBackground(StartAppActivity.java:121)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.IllegalStateException: Method addObserver must be called on the main thread
at androidx.lifecycle.LifecycleRegistry.enforceMainThreadIfNeeded(LifecycleRegistry.java:317)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:172)
at androidx.fragment.app.Fragment.initLifecycle(Fragment.java:471)
at androidx.fragment.app.Fragment.<init>(Fragment.java:451)
at hu.myname.test.fragment.base.BaseFragment.<init>(BaseFragment.java:30)
at hu.myname.test.fragment.lexicon.base.LexiconAbstractFragment.<init>(LexiconAbstractFragment.java:30)
at hu.myname.test.fragment.lexicon.TabsLexiconFragment.<init>(TabsLexiconFragment.java:11)
at hu.myname.test.game.dbs.lexicon.MyDatabase.<clinit>(MyDatabase.java:27)
at hu.myname.test.game.dbs.lexicon.MyDatabase.runStatic(MyDatabase.java:49)
at hu.myname.test.activity.StartAppActivity$1.doInBackground(StartAppActivity.java:121)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
I tried to change the async task to different background solutions like threads and executors but it throws the very same error.
Caused by: java.lang.IllegalStateException: Method addObserver must be called on the main thread
What is going on? I simple updated a few libraries, didn't write new code. I feel like Android development is putting down the rails while standing in front of a train.
Any insights?
Your init function of MyDatabase is creating a Fragment. That Fragment is trying to observe it's Activity's lifecycle, which is not allowed to be done on any thread but the main. Refactor your code so that none of your database code makes any UI calls. Those two subsystems shouldn't be combined like that anyway