Android 如何从任何活动中停止服务上运行的线程?
我有一个在主UI线程上运行的服务,从那里我启动一个新线程,每30秒重复一个方法。我一直试图在onpause()方法上停止线程的其他活动(当设备进入睡眠状态时),但这不起作用。我做错什么了吗?有人能帮忙吗 我的重复任务线程Android 如何从任何活动中停止服务上运行的线程?,android,multithreading,service,handler,Android,Multithreading,Service,Handler,我有一个在主UI线程上运行的服务,从那里我启动一个新线程,每30秒重复一个方法。我一直试图在onpause()方法上停止线程的其他活动(当设备进入睡眠状态时),但这不起作用。我做错什么了吗?有人能帮忙吗 我的重复任务线程 HandlerThread hThread = new HandlerThread("HandlerThread"); hThread.start(); final Handler handler = new Handler(hThread.getLooper
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);
如图所示为了停止该操作,您需要在处理程序上发送一条停止消息(并且您实际上不需要更复杂的操作和类) 为此,实现创建一个方法,当处理程序接收到另一条消息时,该方法实际确定处理程序是否应该停止 例如,实现一个名为
AlarmManager
的Singlethon类来处理重复的任务
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);
}
}
如您所见,这会延迟处理重复的步骤,并在每次执行时打印日志消息(当前由方法参数设置),并且在停止时还会打印日志
为了控制这个流程,只需将它与您的活动
生命周期挂钩即可
@Override
protected void onPause() {
super.onPause();
AlarmManager.getInstance().stopExecution();
}
@Override
protected void onResume() {
super.onResume();
AlarmManager.getInstance().scheduleExecutions(0,3000);
}
为了停止该操作,您需要在处理程序上发送一条停止消息(并且您实际上不需要更复杂的操作和类) 为此,实现创建一个方法,当处理程序接收到另一条消息时,该方法实际确定处理程序是否应该停止 例如,实现一个名为
AlarmManager
的Singlethon类来处理重复的任务
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);
}
}
如您所见,这会延迟处理重复的步骤,并在每次执行时打印日志消息(当前由方法参数设置),并且在停止时还会打印日志
为了控制这个流程,只需将它与您的活动
生命周期挂钩即可
@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;
}
我不知道这是否是最好的方法,但你为什么不检查一下呢 例如:
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;
}
您需要提供在
onPause()
中执行的操作的代码。一般来说,您需要将服务
和活动
视为应用程序的独立组件,而不是直接从一个组件接触另一个组件。使用Intent
s或绑定服务进行交互。@LarrySchiefer感谢您的回答,但我恐怕不明白您在说什么。你能详细说明一下吗?你是在使用安卓服务
来实现这一点,还是说你是可运行的
你正在向后台线程发布你的“服务”?@LarrySchiefer从主UI线程上运行的我的服务创建一个新线程来调用另一个intentservice。runnable方法创建了一个新线程,与服务运行的线程不同。如果您使用服务
派生类来启动IntentService
派生类,则很可能会使其变得比需要的复杂得多。所有Service
组件都在主线程上运行其主入口点(onStartCommand()
,onCreate()
,等等)。例外情况是onBind()
。IntentService
会自动生成一个临时线程来处理传入的Intent
,然后在没有更多的“Intent”需要处理时退出。您需要为在onPause()中执行的操作提供代码。一般来说,您需要将服务
和活动
视为应用程序的独立组件,而不是直接从一个组件接触另一个组件。使用Intent
s或绑定服务进行交互。@LarrySchiefer感谢您的回答,但我恐怕不明白您在说什么。你能详细说明一下吗?你是在使用安卓服务
来实现这一点,还是说你是可运行的
你正在向后台线程发布你的“服务”?@LarrySchiefer从主UI线程上运行的我的服务创建一个新线程来调用另一个intentservice。runnable方法创建了一个新线程,与服务运行的线程不同。如果您使用服务
派生类来启动IntentService
派生类,则很可能会使其变得比需要的复杂得多。所有Service
组件都在主线程上运行其主入口点(onStartCommand()
,onCreate()
,等等)。例外情况是onBind()
。IntentService
会自动生成一个临时线程来处理传入的Intent
,然后在不再需要处理“Intent”时退出。您能给我更多关于它的信息吗,比如在哪里放置该方法?在我的服务中,并通过服务类的实例访问它?另外,使用.quit()和.interrupt()不是一种不推荐的方法吗?上面的代码包含在某种类型的类中,因为此方法同时访问hThread
和handler,它应该转到同一个类,以便能够访问这些字段。因此,该方法转到我的服务类,而我只是通过服务类的实例访问它?@AnninosKyriakou您可以这样做,或者您可以将此功能包装到另一个类中,例如AlarmManager(可以作为单例实现)这暴露了一些用于控制流的方法(stopAlarms()、startAlarms()等),上面的代码进入AlarmManagerAlarm Manager无法工作,因为它不接受在少于一分钟的时间段内重复的任务。Android开发者页面建议在一分钟内使用处理程序。你能给我更多的信息吗,比如在哪里放置该方法?在我的服务中,并通过服务类的实例访问它?另外,使用.quit()和.interrupt()不是一种不推荐的方法吗?上面的代码包含在某种类型的类中,因为此方法同时访问hThread
和handler