0

与标题不同,我会尽量做到清晰、简洁和中肯(希望这不是 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 的上下文。

4

1 回答 1

0

编辑

进一步阅读后,我可能错了,因为服务是通过上下文调用的?如果是这种情况,那么很可能您从不同的活动中调用您的服务,因此,当您从不同的活动中调用 init() 时,使用不同的活动的上下文。如果是这种情况,试试这个,

public class MyService extends Service {
    DBHandler dbHelper;

    public void init() {
        dbHelper = new DBHandler(this);
        dbHelper.getData(ID, 1);
    }
}

与我的其他答案相同,没有传递上下文


上下文,因为不引用活动上下文

public class MyService extends Service {
    DBHandler dbHelper = new DBHandler(this);
}

尝试传递一个上下文:

public class MyService extends Service {
    DBHandler dbHelper;

    public void init(Context context)
    {
        dbHelper = new DBHandler(context);
        dbHelper.getData(ID, 1);
    }
}
于 2012-03-06T18:19:36.047 回答