【问题标题】:Instance of Singleton null单例实例 null
【发布时间】:2017-08-22 17:07:17
【问题描述】:

我在我的 Android 应用中使用了一些单例。从我的onCreate() 中的GlobalApp (extends Application) 类中,它们被初始化如下:

public class GlobalApp extends Application{


    @Override
    public void onCreate() {
        super.onCreate();

    DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext()); 
    MySingleton.init(databaseHelper); 

    }
}

还有单例:

public class MySingleton{

   static MySingleton instance; 
   DatabaseHelper databaseHelper; 

   public static void init(DatabaseHelper databaseHelper){
      instance = new MySingleton(databaseHelper);
   }

}

我收到我的应用程序崩溃,这清楚地表明该实例是 null 有时在我的应用程序运行时。最奇怪的是:这些崩溃只发生在三星 Galaxy S5 上!

我的理解是

  1. 我的application 类的onCreate() 方法保证在我的应用启动时被调用

  2. Singleton 上的实例永远不会变为 null,除非应用程序将完全重新启动(在这种情况下,它应该由我的 application 类重新创建)。

这是怎么回事?

PS:我知道 Singletons 有点不受欢迎,扩展 application 类也不是每个人都推荐的,但这不是重点。

编辑: 只是为了澄清,代码在 99% 的时间里都能正常工作。问题不在于如何实现单例模式,而是我(或任何)应用程序的生命周期如何导致单例的instanceapplication 的@ 中创建时变为null 987654334@.

【问题讨论】:

  • 您需要在init方法中为databaseHelper提供参考。喜欢this.databaseHelper = databaseHelper;
  • 能否请您发布实际代码?因为上述尝试在静态上下文 (init) 中访问非静态字段 (instance),这是一个编译时错误。
  • @dhke 是的,我编辑了那个。
  • 您想要应用程序实例吗? CustomApp.getInstance() 这样的???
  • @NullByte 你真的读过这个问题吗?

标签: java android singleton


【解决方案1】:

我像我的方式一样在我的应用程序中使用单例方法,这对我来说很好

        public class AddEventModel {

            private String event_name;
            private String event_image;
            private static AddEventModel _instance;

        //For Single Ton

        public static AddEventModel get_instance() {
                return _instance;
            }

            public static AddEventModel getInstance() {
                if (_instance == null) {
                    _instance = new AddEventModel();
                }
                return _instance;
            }
         public static void set_instance(AddEventModel _instance) {
                AddEventModel._instance = _instance;
            }

        //Getter setter for model.
            public String getEvent_image() {
                return event_image;
            }

            public void setEvent_image(String event_image) {
                this.event_image = event_image;
            }

            public String getEvent_name() {
                return event_name;
            }

            public void setEvent_name(String event_name) {
                this.event_name = event_name;
            }

要在单例中设置值,如下所示,

        edtEventName.addTextChangedListener(new TextWatcher() {

                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
    //Save edit text value in single ton instance.  
                AddEventModel.getInstance().setEvent_name(edtEventName.getText().toString().trim());
                    }

                    @Override
                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    }

                    @Override
                    public void afterTextChanged(Editable s) {

                    }
                });

从单例中获取价值,

     @Override
            public void onResume() {
                super.onResume();

        // Set same value saved in single ton before in onResume. 
        edtEventName.setText(AddEventModel.getInstance().getEvent_name());

        }

尝试这样使用单例,希望对你有所帮助。

【讨论】:

    【解决方案2】:

    使用下面的代码来你的 singlton calass..

    public class SingletonModel {
     private static SingletonModel instance;
     public DatabaseHelper databaseHelper; 
    
    
     public synchronized  static SingletonModel getSingletonModel() {
    
         if (instance == null) {
             instance = new SingletonModel();
         }
         return instance;
    
     }
    
     private void SingletonModel(){}
    
     }
    

    【讨论】:

    • 我需要一个需要创建上下文的 DatabaseHelper,所以如果我在 getInstance 中延迟初始化实例,我需要在每个 getInstance 中传递 DatabaseHelper 或上下文。
    【解决方案3】:

    请检查你的应用程序内的清单文件你是否把 android:name="" 像:

    <application
            android:name=".application.DoodhwaalaApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
    

    【讨论】:

      【解决方案4】:

      您应该有一个接受 DatabaseHelper 对象的构造函数也将实例设为静态...

      public class MySingleton {
      
          static MySingleton instance;
      
          DatabaseHelper databaseHelper;
      
          public/private MySingleton(DatabaseHelper databaseHelper) {
              // TODO Auto-generated constructor stub
          }
      
          public static void init(DatabaseHelper databaseHelper) {
              instance = new MySingleton(databaseHelper);
          }
      }
      

      【讨论】:

      • 为了清楚起见,发布的课程被缩写。以 Databasehelper 作为参数的构造函数当然存在。
      【解决方案5】:

      单例应该有一个私有构造函数 因此,您可以这样做的唯一事实

       instance = new MySingleton(databaseHelper);
      

      在与 MySingleton 不同的类中使其与 Singleton 有所不同

      您应该通过公共静态方法获取唯一现有的实例,例如

       instance = MySingleton.getInstance(databaseHelper);
      

      如果你需要它,在它的实现中小心验证没有返回 null 的可能性

      【讨论】:

        【解决方案6】:

        创建单例类的另一种方法是将私有构造函数与类实例一起声明为 static-final,这将在类加载时创建您的单例对象。但请确保在 MySingleton 类加载到 JVM 之前初始化 DatabaseHelper 对象。

        更多详情请参考以下示例。

        public class MySingleton {
        
            public static final MySingleton singleton = new MySingleton(DatabaseHelper databaseHelper);
            DatabaseHelper databaseHelper=  null;
        
            private MySingleton(DatabaseHelper databaseHelper) {
                this.databaseHelper = databaseHelper;
            }
        
            public MySingleton getInstance() {
                return singleton;
            }
        }
        

        【讨论】:

          【解决方案7】:

          您应该陷入多线程问题:在一个线程中您设置了没有 volatile 修饰符(或同步部分)的单例,然后在另一个线程中您看到了陈旧的值。

          【讨论】:

          • 从问题中很清楚这不是多线程问题...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-25
          • 2011-06-10
          • 2012-02-17
          相关资源
          最近更新 更多