I am posting this question here after it having been determined to be "off-topic" for stackoverflow, and "too hypothetical" for codereview. I am experimenting with different singleton-style design patterns for an app component having to do with app-wide sound effects and speech. My theory is that while often frowned upon, by making these types of objects global/static/singleton-like will have advantages such as: - Memory use being more stable/constant with a predictable baseline, making OOM errors easier to foresee. - Expensive initializations within these objects (such as TTS engines and large audio buffers) will happen once only. - Sounds are not cut short by activity transitions. - Memory leaks caused by constant and laggy de-and-re-initializations of objects (for example the Google TTS engine) can be avoided by having a single global instance. My question is: "Is the design pattern shown in my code sample feasible / acceptable / solid?" ... and by this I don't mean in your opinion -- I mean is there someone out there with more experience than me (not hard to find) that can see some reason why this code would be bug-prone? I have mainly used the help of [this article][1]. manifest: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.boober.speechsingletonsimplifiedunit"> <application android:name="App" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SettingsActivity" > </activity> </application> <!-- android:screenOrientation="portrait" --> </manifest> Application Class: package com.example.boober.speechsingletonsimplifiedunit; import android.app.Application; import android.content.Context; import android.util.Log; import com.squareup.leakcanary.LeakCanary; public class App extends Application { private static Context appContext; public static GodOfSpeechSingleton GOSS; @Override public void onCreate() { super.onCreate(); // BEGIN LEAK CANARY CODE: if (LeakCanary.isInAnalyzerProcess(this)) { // This process is dedicated to LeakCanary for heap analysis. // You should not init your app in this process. return; } LeakCanary.install(this); // END LEAK CANARY CODE, PROCEED... Log.i("XXX", "App.onCreate() called."); appContext = this; GOSS = new GodOfSpeechSingleton(); } public static Context getAppContext() { return appContext; } } The "GOSS": package com.example.boober.speechsingletonsimplifiedunit; import android.speech.tts.TextToSpeech; import android.util.Log; import java.util.HashMap; import java.util.Locale; import java.util.Random; public class GodOfSpeechSingleton { // aka "the GOSS" private boolean thisClassHasBeenInitAlready = false; TextToSpeech tts1; boolean tts1IsInit; public GodOfSpeechSingleton() { Log.i("XXX", "GOSS constructor called."); } // This method body was created/moved (execution delayed) from the constructor to here // because when constructor was called from Application.onCreate(), // the code "android.content.Context.getPackageManager()" inside the TTS // causes a null pointer exception. public void initFromMainActivity(String caller) { if (!caller.equals("MainActivity")) { return; } if (thisClassHasBeenInitAlready) { Log.i("XXX", "GOSS init already."); return; } thisClassHasBeenInitAlready = true; tts1 = new TextToSpeech(App.getAppContext(), new TextToSpeech.OnInitListener() { @Override public void onInit(int i) { tts1IsInit = true; } }, "com.google.android.tts"); } public void speak(String stringToSpeak, Locale localeToUseForThisUtterance) { if (!tts1IsInit) { Log.i("XXX", "speak() called, but tts1 not init yet!"); return; } tts1.setLanguage(localeToUseForThisUtterance); tts1.speak(stringToSpeak, TextToSpeech.QUEUE_FLUSH, null); } } MainActivity: package com.example.boober.speechsingletonsimplifiedunit; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import java.util.Locale; public class MainActivity extends AppCompatActivity { // LIFECYCLE @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("XXX", "Main.onCreate() called."); App.GOSS.initFromMainActivity("MainActivity"); } @Override protected void onDestroy() { Log.i("XXX", "Main.onDestroy() called."); super.onDestroy(); } // BUTTON PRESSES public void settingsButtonPressed(View ignored) { Intent intent = new Intent(this, SettingsActivity.class); startActivity(intent); } public void speakButtonPressed(View ignored) { App.GOSS.speak("you are in the main activity!",new Locale("en")); } } SettingsActivity: package com.example.boober.speechsingletonsimplifiedunit; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import java.util.Locale; public class SettingsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); } // BUTTON PRESSES public void speakButtonPressed(View ignored) { App.GOSS.speak("you are in the settings activity!", new Locale("en")); } } [1]: https://nfrolov.wordpress.com/2014/07/12/android-using-context-statically-and-in-singletons/