NPE при обращении к переменной, которая существует в службе, которая инициализируется базой данных, для использования в действии - PullRequest
0 голосов
/ 06 марта 2012

В отличие от названия, я постараюсь быть максимально ясным, лаконичным и по возможности точным (надеюсь, это не TL; DR). Я знаю, что название сложно понять, так что, надеюсь, мой вопрос не будет , У меня есть NPE, который я не могу отследить ни в трассировке стека, ни в режиме отладки (при запуске eclipse). Трассировка стека указывает на линию, но независимо от того, что я изменяю, я не могу заставить ее работать без выброса NPE (я укажу на конкретную строку позже). Итак, у меня есть Activity, SQLiteOpenHelper и Сервис. В дополнение к этим трем классам я включу фрагмент из четвертого класса, мой класс Splash. Вышеупомянутая служба запускается через мой класс Splash, используя этот код (я объясню, почему я включил это позже):

startService(new Intent(getApplicationContext(), MyService.class));

Важно отметить, прежде чем перейти к тому, что переменная "ID" в MyService.class установлена ​​другим действием, которое я не буду здесь включать. Просто знайте, что переменная действительно установлена ​​правильно, она изменяется правильно при изменении пользователем, и что я поместил операторы 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 (), вот где появляются гремлины. Что бы я ни делал, я не могу заставить это работать. По какой-то причине, используя 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, пока мои глаза не кровоточат. Поискал гугл. Ничто, нигде не нажимает свет в моей голове, чтобы сказать: «О, это то, что я делаю неправильно». Также (я задавал этот вопрос ранее, но он был закрыт, потому что я задал его без подтверждающих данных). разница (если таковая имеется) между созданием экземпляра моего сервиса путем объявления его как новой переменной (как я делал в своем действии выше, объявив MyService fooService = new MyService ()) по сравнению с простым запуском сервиса, как я это сделал в своем классе заставки с использованием Намерение в самом начале этого вопроса.

Разница их? Я создаю его, потому что, если я просто вызываю службу (то есть, используя MyService.name вместо fooService.name в моей Activity выше), я должен установить переменную 'name' в static ..., что, в свою очередь, означает, что я необходимо установить для dbHelper значение static ..., с которым SQLiteHelper вообще не согласен (не может сделать статическую ссылку на нестатические методы в sqliteopenhelper).

Надеюсь, этой информации достаточно. Я могу включить пастбин в трассировку стека, если это необходимо, но я должен предупредить вас, я немного урезал приведенный выше код, чтобы привести его в соответствие, и изменил имена классов и переменных, чтобы сделать больше смысл в этом ограниченном контексте. В скорлупе ореха точка трассировки стека указывает на вышеуказанное действие, затем указывает на строку MyService.init (), которая затем (наконец) указывает на строку name = DbHelper (ID, 1) в службе. Спасибо за любую помощь !!!

РЕДАКТИРОВАТЬ: В ореховой скорлупе проблема заключается в передаче контекста и в какой тип контекста вы передаете. Для тех, кто читает это и имеет ту же или похожую проблему: попробуйте изменить контекст, который вы передаете в SQLiteOpenHelper.

1 Ответ

0 голосов
/ 06 марта 2012

РЕДАКТИРОВАТЬ

После дальнейшего чтения я могу ошибаться, так как сервисы вызываются с контекстом ?.Если это так, то, скорее всего, вы звоните в свой сервис из разных действий и, следовательно, используете контекст другого действия, когда вы вызываете init () из разных действий.Если это так, попробуйте это,

public class MyService extends Service {
    DBHandler dbHelper;

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

То же, что и мой другой ответ без передачи контекста


context равно null потому что это не относится к контексту активности

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...