Странное исключение NullPointerException с сервисом

У меня есть запущенная служба, и некоторые действия должны быть привязаны к ней, чтобы получить некоторые данные, прежде чем устанавливать представления. Все работает нормально, но иногда (редко) я получал исключение NullPointerException. Моя упрощенная деятельность:

public class MyActivity extends Activity {
    TextView tvName;
    boolean mIsMyServiceBound;
    MyService mMyService;

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            MyService.MyServiceBinder myServiceBinder = (MyService.MyServiceBinder) service;
            mMyService = myServiceBinder();
            mIsMyServiceBound = true;

            // Set up views
            tvName.setText(mMyService.getName());
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            mIsMyServiceBound = false;
            mMyService = null;
        }
    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         setContentView(R.layout.yourlayout);
        tvName = (TextView) findViewById(R.id.tv_name);
        ...
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, ChatService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        mIsChatServiceBound = true;
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mIsChatServiceBound) {
            unbindService(mConnection);
            mIsChatServiceBound = false;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        tvName = null;
    }
}

Ну обычно нормально работает. Но у меня есть исключение NullPointerException при выполнении:

tvName.setText(mMyService.getName());

Ошибка говорит, что tvName равно null, но я не понимаю, как это возможно, так как он будет вызываться после onCreate. Эта ошибка возникает редко, но это довольно раздражает. Может ли активность быть уничтожена, но прослушиватель подключения к службе не отменен? Если это правда, как я могу отменить это подключение к службе, когда действие уничтожено?

Заранее спасибо!


comment
Вы не расширяете Activity или что-то подобное, пожалуйста, не упрощайте свой код, который вы публикуете здесь. Возможно, вы создаете больше ошибок, чем у вас есть, и мы не сможем вам помочь.   -  person yennsarah    schedule 29.02.2016
comment
Я отредактировал код, я тоже забыл его написать. Извините за неудобства, теперь я обновил код.   -  person FVod    schedule 29.02.2016
comment
Почему вы устанавливаете tvName на ноль в onDestroy()? Если вы просто добавите if(tvName == null) //do something else, maybe restart the activity and else tvName.setText(""), вы не получите этот сбой.   -  person yennsarah    schedule 29.02.2016
comment
Попробуйте связать ServiceConntection в onResume() и отвязать его, возможно, также в onPause, в отношении жизненного цикла активности.   -  person yennsarah    schedule 29.02.2016


Ответы (3)


Попробуй это. Вам не хватает

setContentView(R.layout.yourlayout);

в методе onCreate. Вам также нужно расширить класс Activity Надеюсь, это поможет. Спасибо

person Jagjit Singh    schedule 29.02.2016
comment
Спасибо, забыл написать на своем упрощенном примере. Извините, я отредактировал его сейчас, потому что setcontentView находится в моем реальном коде, иначе он всегда будет падать. Спасибо за ваш ответ, у вас есть какие-либо идеи о том, что может произойти? - person FVod; 29.02.2016

Вы забыли написать setcontentView(R.layout.activity_main) в поле Активность.

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setcontentView(R.layout.activity_main)
     tvName = (TextView) findViewById(R.id.tv_name);
}

Надеюсь, что это поможет вам.

person Hiren Patel    schedule 29.02.2016
comment
Спасибо, забыл написать на своем упрощенном примере. Извините, я отредактировал его сейчас, потому что setcontentView находится в моем реальном коде, иначе он всегда будет падать. Спасибо за ваш ответ, у вас есть какие-либо идеи о том, что может произойти? - person FVod; 29.02.2016
comment
@FVod, убедитесь, что в вашем макете есть текстовое представление с идентификатором tv_name. - person Hiren Patel; 29.02.2016
comment
Да, он присутствует. На самом деле эта ошибка просто случается редко. Вот почему я думаю, что здесь есть что-то странное, что-то вроде уничтожения активности, когда прослушиватель подключения к службе еще не запущен. Что вы думаете? - person FVod; 29.02.2016

Попробуйте посмотреть, что произойдет, если вы откроете свою активность и быстро повернете телефон много раз после этого. Если есть проблема с подключением к Сервису и циклом активности, вы сможете обнаружить ее таким образом. Также в качестве обходного пути вы можете попытаться получить ссылку на TextView внутри onServiceConnected и выполнить проверку работоспособности. (Очень странно, но я впервые слышу об этом, возможно, это связано с архитектурой вашего приложения). Также здесь:

MyService.MyServiceBinder myServiceBinder = (MyService.MyServiceBinder)service; mMyService = myServiceBinder();

Вы не должны использовать Службу таким образом, вместо этого создайте Messenger из Binder и используйте обработчик на стороне Службы для выполнения необходимых операций.

person Marius Constantin    schedule 29.02.2016