作为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一致)。我想这是因为在这里不正确地使用单例/活动,现在重写代码以作为服务运行。但也许有一些更好的想法来解决问题?还是一些解决方法?
感谢你提前做出的贡献!
答案 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所说的背景。
此致 斯特凡