与标题不同,我会尽量做到清晰、简洁和中肯(希望这不是 TL;DR)我知道标题很难理解,所以希望我的问题不会。我有一个无法在堆栈跟踪或调试模式(运行 eclipse)中追踪的 NPE。堆栈跟踪指向一行,但无论我更改什么,我似乎都无法在不抛出 NPE 的情况下运行它(稍后我会指出具体的行)。所以我有一个活动、一个 SQLiteOpenHelper 和一个服务。除了这三个类之外,我还将包括第四个类的片段,即我的 Splash 类。上述服务是通过我的 Splash 类启动的,使用以下代码(我将解释为什么我稍后会包含它):
startService(new Intent(getApplicationContext(), MyService.class));
重要的是,我在继续之前指出 MyService.class 中的变量“ID”是由另一个活动设置的,我不会在此处包括。只要知道变量确实设置正确,当用户更改时它会正确更改,并且我已经在代码中的各个点放置了 Log.I(TAG, TEXT) 语句以确保它有效并且数据始终保持一致。我还验证了我的服务正在正确启动,所以这也不是问题。继续。这是我稍后引用的 SQLiteOpenHelper 类中的方法(我已经尽可能地精简代码,因此我只包含相关信息。)
public class DBHandler extends SQLiteOpenHelper {
private static final String _ID = "_id";
private final String KEY_NAME = "name";
public String getData(String ID, int pos) {
String clause = _ID + " = " + ID;
Cursor cr = null;
String result = "";
cr = getReadableDatabase().query(DB_T, columns1, clause, null, null, null, null);
if (cr != null) {
cr.moveToFirst();
result = cr.getString(pos);
}
close();
return result;
}
}
我已经验证了数据库处理程序可以正常工作,因为我可以从代码中的许多其他点调用它而不会出现问题。这个特定的方法每次也有效(事实上,整个类都可以正常工作......除非这个 NPE 弹出)表中的数据在我遗漏的 DB 类的一部分中被初始化,我'已经验证所有这些都有效。所以,继续前进,请假设我的数据库类在我的应用程序中的所有点都可以完美地工作,除了我稍后将向您展示的那一行。接下来我们有我的服务类,它看起来像这样(有问题的行在这里,我稍后会指出):
public class MyService extends Service {
DBHandler dbHelper = new DBHandler(this);
public static String ID = "1";
String name = "";
@Override
public void onCreate() {
super.onCreate();
init();
}
public void init() {
name = dbHelper.getData(ID, 1);
}
}
在方法“public void init()”中,NPE 指向“name = dbHelper.getData(ID, 1);” 请注意,我可以在我的应用程序的其他地方使用这行 EXACT 代码,它可以正常工作……但在这里,它一次又一次地失败。最后我有调用我的服务来获取这些数据的活动。下面,我调用 MyService.init(),这就是 gremlins 出现的地方。无论我做什么,我都无法让它发挥作用。出于某种原因使用 name = dbHelper.getData(ID, 1); 以这种方式使它吹一个垫圈。
public class ActivityInteract extends Activity implements OnClickListener {
MyService fooService = new MyService();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyService.init();
interactInit();
}
private void interactInit() {
setContentView(R.layout.g_interact);
nameText.setText(fooService.name);
}
}
基本上,这让我发疯。我已经通读了android Docs,直到我的眼睛在流血。搜索谷歌。没有什么在我脑海中点击灯说“哦,那是我做错了”另外(我之前问过这个问题,但它被关闭了,因为我在没有支持数据的情况下问它)我想知道通过将我的服务声明为新变量来实例化我的服务(就像我在上面的活动中通过声明 MyService fooService = new MyService() 所做的那样)与像我在启动类中使用意图在这个问题的最开始。
他们有区别吗?我正在实例化它,因为如果我只是调用服务(即在上面的 Activity 中使用 MyService.name 而不是 fooService.name),那么我必须将“name”变量设置为静态......这反过来意味着我必须将'dbHelper'设置为静态... SQLiteHelper 根本不同意(不能对sqliteopenhelper 中的非静态方法进行静态引用)。
我希望这是足够的信息。如果需要,我可以在堆栈跟踪中包含一个 pastebin,但我必须警告你,我已经对上面的代码进行了相当多的修改以使其适合,并更改了类和变量的名称,以便它产生更多在这种有限的背景下有意义。简而言之,堆栈跟踪指向上述活动,然后指向 MyService.init() 行,然后(最终)指向服务中的 name = DbHelper(ID, 1) 行。感谢您的任何帮助!!!
编辑:简而言之,问题在于传递上下文以及您传递的上下文类型。对于阅读此内容并遇到相同或类似问题的任何人:尝试更改您传递给 SQLiteOpenHelper 的上下文。