Android中的Singleton

时间:2013-05-13 08:28:11

标签: android singleton

我已经关注此链接并成功在Android中制作了单例类。 http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

问题是我想要一个对象。就像我有活动A和活动B.在活动A中我从Singleton class访问对象。我使用该对象并对其进行了一些更改。

当我移动到Activity B并从Singleton Class访问该对象时,它给了我初始化的对象,并没有保留我在Activity A中所做的更改。 有没有其他方法来挽救变化? 请高手帮帮我。 这是MainActivity

public class MainActivity extends Activity {
protected MyApplication app;        
private OnClickListener btn2=new OnClickListener() {    
    @Override
    public void onClick(View arg0) {
        Intent intent=new Intent(MainActivity.this,NextActivity.class);
        startActivity(intent);              
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Get the application instance
    app = (MyApplication)getApplication();

    // Call a custom application method
    app.customAppMethod();

    // Call a custom method in MySingleton
    Singleton.getInstance().customSingletonMethod();

    Singleton.getInstance();
    // Read the value of a variable in MySingleton
    String singletonVar = Singleton.customVar;

    Log.d("Test",singletonVar);
    singletonVar="World";
    Log.d("Test",singletonVar);

    Button btn=(Button)findViewById(R.id.button1);
    btn.setOnClickListener(btn2);
}

}

这是NextActivity

public class NextActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next);

        String singletonVar = Singleton.customVar;

        Log.d("Test",singletonVar);
        }}

Singleton班级

public class Singleton
{
private static Singleton instance;

public static String customVar="Hello";

public static void initInstance()
{
if (instance == null)
{
  // Create the instance
  instance = new Singleton();
}
}

public static Singleton getInstance()
{
 // Return the instance
 return instance;
 }

 private Singleton()
 {
 // Constructor hidden because this is a singleton
 }

 public void customSingletonMethod()
 {
 // Custom method
 }
 }

MyApplication

public class MyApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();

 // Initialize the singletons so their instances
 // are bound to the application process.
 initSingletons();
 }

 protected void initSingletons()
 {
 // Initialize the instance of MySingleton
 Singleton.initInstance();
 }

 public void customAppMethod()
 {
 // Custom application method
}
}

当我运行这段代码时,我得到了我已经在Singleton中初始化的Hello,然后是我在MainActivity中给出的World,并再次在logcat中显示NextActivity中的Hello。 我想让它在NextActivity再次显示世界。 请帮我纠正一下。

8 个答案:

答案 0 :(得分:58)

提示:创建单例类在Android Studio中,右键单击项目并打开菜单:

Private Sub cmdLogin_Click()
        'Check to see if data is entered into the Username combo box
    Dim strMyUsername As String
    Dim RS As Recordset
    If IsNull(Me.cbo_Employee) Or Me.cbo_Employee = "" Then
        MsgBox "You Must enter a Username.", vbOKOnly, "Required Data"
        Me.cbo_Employee.SetFocus
        Exit Sub
    End If
    strMyUsername = Me.cbo_Employee.Value

    'Check to see if data is entered into the password box

If IsNull(Me.txt_Password) Or Me.txt_Password = "" Then
    MsgBox "You must enter a Password.", vbOKOnly, "Required Data"
    Me.txt_Password.SetFocus
    Exit Sub
End If

Set RS = CurrentDb.OpenRecordset("SELECT * FROM [Employees Table] WHERE [Username] = '" & strMyUsername & "'", dbOpenSnapshot)

'Check value of password in Employees Table to see if this matches value chosen in combo box
If Me.txt_Password.Value <> Nz(RS!Password) Then
    MsgBox "Password Invalid. Please Try Again", vbOKOnly, "Invalid Entry!"
    Me.txt_Password.SetFocus
    Me.txt_Password = Null
    intLogonAttempts = intLogonAttempts + 1
    'If user enters incorrect password 3 times database will shutdown
    If intLogonAttempts >= 3 Then
        MsgBox "You do not  have access to this database. Please contact your system administrator.", vbCritical, "Restricted Access!"
        Application.Quit
    End If

Else
    Me.txt_Password = Null
    'Open correct form
    Dim strAccessLevel As String

    strAccessLevel = RS!Admins

    If strAccessLevel = "Admin" Then
        MsgBox "Welcome " & RS!EmployeeName
        DoCmd.Close
        DoCmd.OpenForm "A"
    ElseIf strAccessLevel = "Manager" Then
        MsgBox "Welcome " & RS!EmployeeName
        DoCmd.Close
        DoCmd.OpenForm "B"
    ElseIf strAccessLevel = "User" Then
        MsgBox "Welcome " & RS!EmployeeName
        DoCmd.Close
        DoCmd.OpenForm "C"
    End If
End If

End Sub

enter image description here

答案 1 :(得分:44)

编辑:

在Android中实现Singleton并不安全,您应该使用专用于此类模式的库,如Dagger或其他DI库来管理生命周期和注入。


你能从你的代码中发布一个例子吗?

看看这个要点:https://gist.github.com/Akayh/5566992

它有效,但很快就完成了:

MyActivity:首次设置单例+在私有构造函数中初始化mString属性(“Hello”)并显示值(“Hello”)

将新值设置为mString:“Singleton”

启动activityB并显示mString值。 “单身人士”出现......

答案 2 :(得分:30)

很简单,作为一个java,Android也支持单例。 -

Singleton是Gang of Four设计模式的一部分,它被归类为创作设计模式。

- &GT;静态成员:它包含单例类的实例。

- &GT;私有构造函数:这将阻止任何其他人实例化Singleton类。

- &GT;静态公共方法:这提供了对Singleton对象的全局访问点,并将实例返回给客户端调用类。

  1. 创建私有实例
  2. 创建私有构造函数
  3. 使用Singleton类的getInstance()

    public class Logger{
    private static Logger   objLogger;
    private Logger(){
    
            //ToDo here
    
    }
    public static Logger getInstance()
    {
        if (objLogger == null)
       {
          objLogger = new Logger();
       }
       return objLogger;
       }
    
    }
    
  4. 使用单身人士 -

    Logger.getInstance();
    

答案 3 :(得分:18)

拉克什建议的答案很棒但仍有一些描述 Android中的Singleton与Java中的Singleton相同: Singleton设计模式解决了所有这些问题。使用Singleton设计模式,您可以:

  

1)确保只创建一个类的一个实例

     

2)提供对象的全局访问点

     

3)将来允许多个实例而不影响a   单身人士的客户

一个基本的Singleton类示例:

public class MySingleton
{
    private static MySingleton _instance;

    private MySingleton()
    {

    }

    public static MySingleton getInstance()
    {
        if (_instance == null)
        {
            _instance = new MySingleton();
        }
        return _instance;
    }
}

答案 4 :(得分:12)

正如@ this answer中所述@Lazy所述,您可以在Android Studio中的模板中创建单例。值得注意的是,不需要检查实例是否为null,因为静态ourInstance变量首先被初始化。因此,Android Studio创建的单例类实现就像下面的代码一样简单:

public class MySingleton {
    private static MySingleton ourInstance = new MySingleton();

    public static MySingleton getInstance() {
        return ourInstance;
    }

    private MySingleton() {
    }
}

答案 5 :(得分:5)

您正在将单身customVar复制到singletonVar变量中,并且更改该变量不会影响单身中的原始值。

// This does not update singleton variable
// It just assigns value of your local variable
Log.d("Test",singletonVar);
singletonVar="World";
Log.d("Test",singletonVar);

// This actually assigns value of variable in singleton
Singleton.customVar = singletonVar;

答案 6 :(得分:2)

我把我的Singleton版本放在下面:

public class SingletonDemo {
    private static SingletonDemo instance = null;
    private static Context context;

    /**
     * To initialize the class. It must be called before call the method getInstance()
     * @param ctx The Context used

     */
    public static void initialize(Context ctx) {
     context = ctx;
    }

    /**
     * Check if the class has been initialized
     * @return true  if the class has been initialized
     *         false Otherwise
     */
    public static boolean hasBeenInitialized() {
     return context != null;

    }

    /**
    * The private constructor. Here you can use the context to initialize your variables.
    */
    private SingletonDemo() {
        // Use context to initialize the variables.
    }

    /**
    * The main method used to get the instance
    */
    public static synchronized SingletonDemo getInstance() {
     if (context == null) {
      throw new IllegalArgumentException("Impossible to get the instance. This class must be initialized before");
     }

     if (instance == null) {
      instance = new SingletonDemo();
     }

     return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Clone is not allowed.");
    }
}

请注意,可以在主类(Splash)中调用方法初始化,并且可以从其他类调用方法getInstance。当调用者类需要单例但它没有上下文时,这将解决问题。

最后,方法hasBeenInitialized用于检查类是否已初始化。这将避免不同的实例具有不同的上下文。

答案 7 :(得分:1)

在Android中使用单例的最干净和最现代的方法就是使用名为Dependency InjectionDagger 2框架。 Here您可以解释可以使用的范围。 Singleton是这些范围之一。依赖注入并不那么容易,但你应该投入一点时间来理解它。它还使测试更容易。