Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何从任何活动中停止服务上运行的线程?_Android_Multithreading_Service_Handler - Fatal编程技术网

Android 如何从任何活动中停止服务上运行的线程?

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

我有一个在主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);

如图所示

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

例如,实现一个名为
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