openFileOutput在单例类中不能正常工作 - 想法/解决方法?

时间:2011-06-30 17:51:49

标签: java android

作为Android新手开发者,我遇到了一个奇怪的问题。我想创建一个类,它可以处理其他类 - 活动 - 用于以某种特殊方式处理文件的任何方法。让我们说简单,我们会记录一些东西。如果我在一个活动中做跟踪(例如在OnClick监听器中),一切正常:

FileOutputStream fOut = openFileOutput("somefile", MODE_PRIVATE);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.write("Very important foobar");
osw.flush();
osw.close();

但是当我尝试将其包含在某个类中并创建像这样的单例时:

public class Logger extends BaseActivity {
//BaseActivity is the "init" class which extends Activity

public static final Logger INSTANCE = new Logger();
private Logger() { 
// singleton
}

public boolean doLog (String whatToLog) {
 try {
     FileOutputStream fOut = openFileOutput("somefile", MODE_PRIVATE);
 OutputStreamWriter osw = new OutputStreamWriter(fOut);
 osw.write(whatToLog);
 osw.flush();
 osw.close(); }
     catch (IOException ioe) { ioe.printStackTrace(); }  
     return true; }

并从其他活动中调用它

Logger.INSTANCE.doLog("foobar");  

app使用NullPointerException崩溃(与openFileOutput一致)。我想这是因为在这里不正确地使用单例/活动,现在重写代码以作为服务运行。但也许有一些更好的想法来解决问题?还是一些解决方法?

感谢你提前做出的贡献!

5 个答案:

答案 0 :(得分:3)

您将自己的单例基于未作为活动启动的活动。因此,它没有有效的上下文,这是IO调用所必需的。有关更好的单例,请参阅Blundell的answer,只需进行一项更改:根据android.app.Application javadoc,您的单例应通过Context.getApplicationContext()从给定的上下文中获取应用程序上下文。有关其他示例,请参阅why does AndroidTestCase.getContext().getApplicationContext() return null

答案 1 :(得分:0)

我很确定你的错误不是来自你提到的那一行。

在表单

的语句中发生空指针异常
A.B or A.B()

其中A为null。在这一行上,你班上没有这样的东西。

请仔细检查堆栈跟踪,发送并指明行号。

不要忘记在所有文件之前保存文件。

此致  斯特凡

答案 2 :(得分:0)

你应该写一个像这样的单例类:

 import android.content.Context;
 import android.util.Log;

 public final class SomeSingleton implements Cloneable {

private static final String TAG = "SomeSingleton";
private static SomeSingleton someSingleton ;
private static Context mContext;    

/**
 * I'm private because I'm a singleton, call getInstance()
 * @param context
 */
private SomeSingleton(){
      // Empty
}

public static synchronized SomeSingleton getInstance(Context context){
    if(someSingleton == null){
        someSingleton = new SomeSingleton();
    }
    mContext = context.getApplicationContext();
    return someSingleton;
}

public void playSomething(){
    // Do whatever
            mContext.openFileOutput("somefile", MODE_PRIVATE); // etc...
}

public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException("I'm a singleton!");
}
 }

然后你这样称呼它(取决于你从哪里调用它):

 SomeSingleton.getInstance(context).playSomething();
 SomeSingleton.getInstance(this).playSomething();
 SomeSingleton.getInstance(getApplicationContext()).playSomething();

编辑:请注意,这个单例是有效的,因为它不是基于Activity,而是从实例化它的人那里得到一个有效的Context(就像另一个正确启动的Activity)。您的原始单例失败,因为它从未作为活动启动,因此它没有有效的上下文。 -cdhabecker

答案 3 :(得分:0)

你正在使用你的班级我不认为它正在做你想要的。您对openFileOutput的调用失败,因为您的单例没有上下文。它不会经历初始化生命周期阶段,也不会建立任何上下文。

我建议您创建一个服务以允许日志写入并在要记录的对象的“静态”上下文中绑定到该服务,以确保日志请求是原子的。

答案 4 :(得分:0)

您应该在OnCreate方法中调用doLog,而不是在Activity的构造函数中调用。 在此之前,它没有@Dave G所说的背景。

此致  斯特凡