如何从任何 activity 停止服务上的线程 运行?

How to stop a thread running on a service from any activity?

我有一个在主 UI 线程上运行的服务,我从那里启动一个新线程,该线程每 30 秒重复一个方法。我一直试图在 onpause() 方法(当设备进入睡眠状态时)上停止其他活动的线程,但这不起作用。难道我做错了什么?有人可以帮忙吗?

我的重复任务线程

HandlerThread hThread = new HandlerThread("HandlerThread");
    hThread.start();

    final Handler handler = new Handler(hThread.getLooper());
    final long oneMinuteMs = 30 * 1000;

     Runnable eachMinute = new Runnable() {
        @Override
        public void run() {
            Intent service = new Intent(getApplicationContext(), AlarmIntentService.class);
            startService(service);
            handler.postDelayed(this, oneMinuteMs);

        }
    };// Schedule the first execution
    handler.postDelayed(eachMinute, oneMinuteMs);

如所见here

为了停止它,您需要在 Handler 上发送停止消息(并且您实际上并不需要更复杂的操作和 classes) 为此,实现创建一个方法,该方法实际确定您的处理程序在收到另一条消息时是否应该停止。

例如,实现名为 AlarmManager 的 Singlethon class 来处理重复任务

public class AlarmManager implements Handler.Callback {

private static final String TAG = AlarmManager.class.getName();

/**
 * The message "what" sent to the handler in order to stop
 */
private final int STOP_MESSAGE_ID = 0;

private static AlarmManager sInstance;

private Handler mHandler;

private Runnable mExecutionRunnable;

/**
 * Generates a single instance of this class
 */
public static AlarmManager getInstance() {
    if (sInstance == null) {
        sInstance = new AlarmManager();
    }
    return sInstance;
}

/**
 * Private constructor to avoid initializing this class by constructor.
 * {@link #getInstance()} should be used instead in order to assure that only one
 * instance of this class exists
 */
private AlarmManager() {
    mHandler = new Handler(this);
}

@Override
public boolean handleMessage(Message message) {
    switch (message.what) {
        case STOP_MESSAGE_ID:
            //Remove all stop messages
            mHandler.removeMessages(STOP_MESSAGE_ID);
            //Remove all callbacks
            mHandler.removeCallbacks(mExecutionRunnable);
            Log.d(TAG, "Stopping Operations");
            break;
        default:
            mHandler.handleMessage(message);
            break;
    }
    return false;
}

    /**
     * Schedule operations to start after a delay, and the operation will repeat after a period of time specified
     *
     * @param beforeStartDelay Delay in milliseconds before the first start
     * @param repeatTimeDelay Repeat delay in milliseconds between executions
     */
    public void scheduleExecutions(final long beforeStartDelay, final long repeatTimeDelay) {
    mExecutionRunnable = new Runnable() {
        @Override
        public void run() {
//                Intent service = new Intent(getApplicationContext(),     AlarmIntentService.class);
//                startService(service);
            Log.d(TAG, "Executing operation again");
            mHandler.postDelayed(this, repeatTimeDelay);
        }

    };
    mHandler.postDelayed(mExecutionRunnable,beforeStartDelay);

}

/**
 * Cancels the repeating executions
 */
public void stopExecution() {
    mHandler.sendEmptyMessage(STOP_MESSAGE_ID);
}

}

如您所见,这会延迟处理重复步骤,并在每次执行时打印一条日志消息(当前由方法参数设置),并在停止时打印一条日志。

为了控制此流程,只需将其与您的 Activity 生命周期连接起来即可。

@Override
protected void onPause() {
    super.onPause();
    AlarmManager.getInstance().stopExecution();
}

@Override
protected void onResume() {
    super.onResume();
    AlarmManager.getInstance().scheduleExecutions(0,3000);
}

我不知道这是否是最好的方法,但你为什么不检查一下?

例如:

public class Generic {
private boolean isLooping = true;

...
    HandlerThread hThread = new HandlerThread("HandlerThread");
    hThread.start();

    final Handler handler = new Handler(hThread.getLooper());
    final long oneMinuteMs = 30 * 1000;

    Runnable eachMinute = new Runnable() {

        @Override
        public void run() {
            if(isLooping) {
                Intent service = new Intent(getApplicationContext(), AlarmIntentService.class);
                startService(service);
                handler.postDelayed(this, oneMinuteMs);
            }

        }
    };// Schedule the first execution
    handler.postDelayed(eachMinute, oneMinuteMs);

...

public void setLooping(boolean isLooping) {
    this.isLooping = isLooping;
}