0

I tried to use a singleton like this. init() must be called with a context. I called it in the onCreate() of the MainActivity. But there was a problematic situation.

Let's say there is another activity, Activity2. In the MainAcvitiy, I started Activity2. Then, I pressed the home button and used other apps. Now, I came back to my application, and it crashed. I read the log. It seemed that my app had restarted, but MainAcivity was skipped and it started directly from Activity2. This was not something I expected. Since the singleton class was only initialized in the MainActivity, if the app starts from Activity2, it is not initialized.

I could put the initialization code to the onCreate() of all activities, but that seems to be a bad thing. I think I could subclassing Application and do the initialization there. But is that the right place? The documentation says there normally is no need to subclass Application.

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.loser, PID: 32117
java.lang.RuntimeException: Unable to resume activity {com.loser/com.loser.Activity2}: java.lang.RuntimeException: Call init() first.
   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3454)
   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3494)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2757)
   at android.app.ActivityThread.-wrap12(ActivityThread.java)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1496)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6186)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Caused by: java.lang.RuntimeException: Call init() first.
   at com.loser.MySingleton$Companion.getInstance(MySingleton.kt:44)
   at com.loser.Activity2.onResume(Activity2.kt:93)
   at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1270)
   at android.app.Activity.performResume(Activity.java:6788)
   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3431)
   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3494) 
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2757) 
   at android.app.ActivityThread.-wrap12(ActivityThread.java) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1496) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:154) 
   at android.app.ActivityThread.main(ActivityThread.java:6186) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135

2 Answers2

0

I would initialize it in the Application class in the onCreate method and then get() the instance everywhere.

Or You can pass the Context object itself to the get method to init the instance if it's not initialized yet.

if(_instance == null) init();
Ahmed Hegazy
  • 12,395
  • 5
  • 41
  • 64
  • I tried to avoid passing a context every time I get the instance. I mean, currently it is `MySingleton.instance.doSomethng()`, but if I pass a context, it will be like `MySingleton.getInstance(this@MyFragment.context).doSomethng()`. Although by that way, I would not have to use `init()`, that would make the code look ugly. – Damn Vegetables Jan 17 '18 at 10:36
  • I agree with you, but sometimes you don't want to always initialize the object with the Application class unless you need it anywhere in the app (lazy loading). – Ahmed Hegazy Jan 17 '18 at 10:40
  • Not everywhere, but it is and will be used at least in several activities and fragments. And it is needed in the MainActivity right after the app has started. I guess I would use the `Application` way. – Damn Vegetables Jan 17 '18 at 10:47
  • That would make perfect sense to me then! – Ahmed Hegazy Jan 17 '18 at 10:49
  • @DamnVegetables are you passing activity context.? Note that activity context is tied to lifecycle of the activity. – Raghunandan Jan 17 '18 at 10:50
  • I would also check this way of creating a Sigeltone in Kotlin. It looks clearer to me https://github.com/dbacinski/Design-Patterns-In-Kotlin#singleton – Ahmed Hegazy Jan 17 '18 at 10:51
  • I just passed the MainActivity's this. Thank you for the information. – Damn Vegetables Jan 17 '18 at 11:30
0

If you only need the Context you can use any context or getApplicationContext(). The initialization has to work this way. If not, we would need more informations (log).

Antonio Vlasic
  • 337
  • 3
  • 15