0

对于我的 Android 应用程序,我编写了一个由应用程序中各种活动所需的实用程序函数组成的类。在这个类中,我需要一个上下文变量(用于处理文件)以及一个首选项管理器和首选项编辑器的实例.此外,需要一个长整数来表示当前日期作为时间戳:

private static long today;
private static Context myContext;
private static SharedPreferences sharedPrefs;
private static Editor editor;

这是初始化这些变量的正确方法。我已经尝试通过如下所示的私有构造函数来执行此操作,但我遇到了错误。

private NetworkController()
{
    //Getting the Unix timestamp for today
    GregorianCalendar aDate = new GregorianCalendar();
    GregorianCalendar tDate = new  
    GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),  
    aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
    today = (tDate.getTimeInMillis())/1000; 
     //The preferences manager for reading in the preferences
    sharedPrefs = PreferenceManager.getDefaultSharedPreferences(myContext);
    //The preferences editor for modifying the preferences values
    editor = sharedPrefs.edit();
}

一种方法是在使用它的每个活动中创建此类的一个实例,但我不想这样做。还有其他方法吗?

4

4 回答 4

1

如果您有一组随处使用的东西并且只想要一个实例,则可以使用所谓的单例。例如,这里有一个非常简单的,它包含一个名为 的整数level

public class Utility {
    private static Utility theInstance;

    public int level;

    private Utility() {
        level = 1;
    }

    public static getUtility() {
        if (theInstance == null) {
            theInstance = new Utility();
        }
        return theInstance;
    }

}

然后你可以像这样使用它:

Utility u = Utility.getUtility();
u.level++;

然而,许多人不鼓励使用单例,因为它们会导致程序行为混乱。关于这个主题的一篇好文章是Singletons are Pathological Liars。单例在某些情况下可能很有用,但您应该注意使用它们所涉及的陷阱。

于 2012-05-21T22:10:55.553 回答
0

@Greg 是对的,只是不要使用任何静态的东西来做你想做的事。您没有理由不想在这里放置普通对象。将上下文作为参数传递,并在需要它们为您服务时实例化您的对象:

private long today;
private Context myContext;
private SharedPreferences sharedPrefs;
private Editor editor;

public NetworkController( Context context )
{
    this.context = context;
    //Getting the Unix timestamp for today
    GregorianCalendar aDate = new GregorianCalendar();
    GregorianCalendar tDate = new  
    GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),  
    aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
    today = (tDate.getTimeInMillis())/1000; 
     //The preferences manager for reading in the preferences
    sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.context);
    //The preferences editor for modifying the preferences values
    editor = sharedPrefs.edit();
}

单例是一种糟糕的编程方式,它使测试变得非常困难。即使你还没有使用测试,也不要使用单例,当事情变得更复杂时,这会导致代码质量很差,并且会变得一团糟。

于 2012-05-21T22:16:44.907 回答
0

在这里你可以这样做:

public class NetworkController {

     SharedPreferences settings;
     SharedPreferences.Editor editor;


     public NetworkController(Context context){
        settings = PreferenceManager.getDefaultSharedPreferences(context);
        editor = settings.edit();
     }

     public void saveName(String name){
          editor.putString("name", name).commit();
     }

     public String getName(){
          return settings.getString("name");
     }

     public static long getTimeStamp(){
          return System.currentTimeMillis();
     } 

}

您可以使用如下类:

 NetworkController prefs = new NetworkController(context); // Context being an Activity or Application
 prefs.saveName("blundell");
 System.out.println(prefs.getName()); // Prints 'blundell';
 System.out.println(NetworkController.getTimeStamp()); // Prints 1294931209000

如果您不想在每个类中创建一个实例,您可以在应用程序的实例上创建并始终引用它:

public class MyApplication extends Application {

     private NetworkController myPrefs;

     public NetworkController getPrefs(){
          if(myPrefs == null){ // This is called lazy initialization
             myPrefs = new NetworkController(this); // This uses the Application as the context, so you don't have issues when Activitys are closed or destroyed
          }
          return myPrefs;
     }

}

您需要添加MyApplication到您的清单:

<application 
    android:name="com.your.package.MyApplication"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">

要使用这个单一实例,您可以这样做:

public class MyActivity extends Activity {


     public void onCreate(Bundle savedInstanceState){
          super(savedInstanceState);

          NetworkController prefs = ((NetworkController) getApplicationContext()).getPrefs();

          // use this object just like shown above
          prefs.saveName("blundell"); // etc
     }

}
于 2012-05-21T22:17:20.760 回答
0

这里已经发布了很多很好的建议,但我想这种“实用程序”/“帮助程序”功能的另一种方法是简单地传递您需要逻辑处理的参数。Context在您的情况下,您可以简单地将其传入,而不是尝试使逻辑在本地引用上工作:

public static void NetworkController(Context context) {
    //Getting the Unix timestamp for today
    GregorianCalendar aDate = new GregorianCalendar();
    GregorianCalendar tDate = new  
    GregorianCalendar(aDate.get(Calendar.YEAR),aDate.get(Calendar.MONTH),  
    aDate.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
    long today = (tDate.getTimeInMillis())/1000; 
    //The preferences editor for modifying the preferences values
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
    ...
}

您可以即时计算/推断的其他变量。这可能意味着更多的垃圾收集,但在内存管理方面应该是相对安全的。

于 2012-05-22T00:09:19.050 回答