【问题标题】:Application singleton use in AndroidAndroid 中的应用程序单例使用
【发布时间】:2017-04-04 02:41:58
【问题描述】:

我有一个 facebook 初始化 sdk 调用,我需要它来初始化应用程序启动的那一刻:

我想使用我的应用程序类来做到这一点。例如:

public class App extends Application {

@Override
public void onCreate() {
    super.onCreate();
    FacebookSdk.sdkInitialize(getApplicationContext());
}
}

我有 facebook 登录按钮的主要活动:

public class MainActivity extends AppCompatActivity {
@BindView(R.id.login_button)
LoginButton loginButton;

private CallbackManager callbackManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);

    callbackManager = CallbackManager.Factory.create();
    loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult loginResult) {

        }

        @Override
        public void onCancel() {

        }

        @Override
        public void onError(FacebookException error) {

        }
    });
}
}

如何调用我的应用程序单例?如何使其 onCreate() 工作?

【问题讨论】:

  • android-studio 标签用于询问有关该工具的问题
  • 应用程序启动时应用程序类运行,那么你的问题是什么?你想手动运行它吗?

标签: java android singleton facebook-sdk-3.0


【解决方案1】:

当您扩展 android.app.Application 类时,您不必显式调用 onCreate。但请确保您在 AndroidManifest.xml 中指定它, 像这样 android:name="fully-qualified name" 例如:android:name="com.example.MyApplication"

您不必实现单例模式,因为应用程序已经是单例,您的应用程序只有一个实例。 而且,要获取 Application 实例或您定义的 Application 的任何自定义子级,您只需调用 context.getApplication()

参考https://developer.android.com/reference/android/app/Application.html

【讨论】:

    【解决方案2】:

    要让您的 App 类 singleton 遵循 单例设计模式

    public class App
      {
        // Create the instance
        private static App instance;
        public static App getInstance()
        {
             if (instance== null) {
                    synchronized(App.class) {
                            if (instance == null)
                                    instance = new App();
                            }
                    }
                    // Return the instance
                    return instance;
        }
    
        private App()
        {
            // Constructor hidden because this is a singleton
        }
    
        public void initFBSdk()
        {
            FacebookSdk.sdkInitialize(getApplicationContext());
        }
    }
    

    然后在任何其他类中使用它:

    App.getInstance().initFBSdk();
    

    如果这是您的要求..

    【讨论】:

    • 如果android无法实例化应用程序obj,应该如何启动你的应用程序?
    • 应用程序构造函数应该可以被 Android 访问。你不应该隐藏它。
    • 将构造函数设为私有会在应用启动期间引发 java.lang.IllegalAccessException: access to constructor not allowed 错误。此外,synchronized() 中的 this 显示错误 cannot be referenced from a static context
    • 这是 Java 中的通用单例设计模式,在 Android“应用程序类”中不起作用,因为应用程序类由 ART 通过其构造函数调用,因此构造函数不能是私有的。要在应用程序启动时初始化 SDK,只需在 onCreate 中初始化,它将作为 Application 类在任何 Activity/服务之前运行。
    【解决方案3】:

    我认为您正在尝试在 java 中创建线程安全的单例。 这是我们App 类所需的代码:

    public class App extends Application 
    {
        private static App instance;
    
        public static App getAppInstance() { return instance; }
    
        @Override
        public void onCreate() 
        {
            super.onCreate();
            instance = this;
        }   
    
        public void initFacebookSdk()
        {
            FacebookSdk.sdkInitialize(getApplicationContext());
        }
    }
    

    这只是对自身的引用。我们想为多线程实现一个单例。然后我们将创建另一个类,在其构造函数中封装App 类,如下所示:

    public class SingletonApp
    {
        private static App appInstance = null;
        private static SingletonApp instance = null;
        private static final Object mutex = new Object();
    
        public static SingletonApp getInstance() 
        {
            SingletonApp r = instance;
            if (r == null) {
                synchronized (mutex) {  // While we were waiting for the sync, another 
                    r = instance;       // thread may have instantiated the object.
                    if (r == null) {  
                        r = new SingletonApp();
                        instance = r;
                    }
                }
            }
    
            return r;
        }
    
        private SingletonDemo()
        {
           // Direct access the Application context calling
           appInstance = App.getAppInstance();
        }
    
        public static getAppInstance()
        {
           return getInstance().appInstance;
        }
    }
    

    然后在您的 MainActivity 类中,您可以导入静态实例并在您的代码中使用它:

    import static your.package.name.SingletonApp.getAppInstance;
    

    例如,您可以在 MainActivity 类中使用它,只需像这样调用方法 initFacebookSdk()

    public class MainActivity extends AppCompatActivity
    {
        ...
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initFacebookSdk();
    
            ...
        }
    }
    

    【讨论】:

    • 私有应用程序构造函数将无法工作,因为系统将无法实例化它。
    • @MbengueAssane 您认为这是一个声明吗?如果是一个声明,我会要求您先对其进行测试,然后才能发表错误的评论并误导用户。谢谢
    • 已测试!我收到一个错误:java.lang.IllegalAccessException: private App() is not accessible from class android.app.Instrumentation
    • 我发布了一个在我的项目中使用的解决方案。无论如何我更新了我的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    相关资源
    最近更新 更多