Мне нужно отменить таймер, запущенный в классе обслуживания из MainActivity, но получить исключение нулевой ссылки - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть класс типа обслуживания, который запускает таймерную задачу в методе onCreate, и мне нужно остановить таймер из MainActivity, когда пользователь нажимает кнопку. Я знаю, что должен держать ссылку на таймер в своем сервисе, но я не могу понять, как это сделать, и мне нужна помощь, пожалуйста!

пожалуйста, посмотрите на мой код

package com.example.timertest;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        startService(new Intent(this, TimeService.class));

    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.button){
            // i need here to call mTimer.cancel() in TimeService.class
            //
        }
    }
}

// и вот TimeService.java

package com.example.timertest;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.Toast;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimeService extends Service {
    public Timer mTimer;
    private Handler mHandler = new Handler();
    long NOTIFY_INTERVAL = 60 * 1000 * 1; // 1 min

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        if (mTimer != null) {
            mTimer.cancel();
        } else {
            mTimer = new Timer();
        }
        mTimer.scheduleAtFixedRate(new RefreshDataTimerTask(), 0, NOTIFY_INTERVAL);
    }

    class RefreshDataTimerTask extends TimerTask {

        @Override
        public void run() {
            mHandler.post(new Runnable() {

                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), getDateTime(), Toast.LENGTH_LONG).show();
                }
            });
        }

        private String getDateTime() {
            SimpleDateFormat sdf = new SimpleDateFormat("[yyyy/MM/dd - HH:mm:ss]");
            return sdf.format(new Date());
        }
    }
}

// и сервис зарегистрирован в манифесте

<service android:name=".TimeService"/>

Я пытался вызвать mTimer.cancel (), но получил нулевую ссылку, потому что, кажется, я создал новый экземпляр класса обслуживания.

В этом примере показан тост с датой и временем каждую минуту, я хочу, чтобы, например, прошло, например, 15 секунд, и я нажимаю кнопку, таймер должен быть отменен и снова начать отсчет 60 секунд с начала. Внутри этого сервиса у меня есть много других вещей, таких как уведомления, каналы, общие настройки и т. Д., Поэтому будет хорошо, если я смогу работать только с объектом таймера.

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

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

После успешного связывания вы можете добавить метод в вашем сервисе для остановки таймера:

public void stopMyTimer() {
    mTimer.cancel();
}

И вызвать этот метод из Activity

0 голосов
/ 12 апреля 2019

Это может быть не самой лучшей практикой, но вы можете получить доступ к общедоступным значениям, непосредственно обращаясь к классу:

TimeService.mTimer.cancel()

, который должен работать, потому что службы функционируют аналогично синглетам, так как каждый вызов startService должен бытьвызывая тот же экземпляр.

...