我对我的应用程序的设计感到困惑。我需要不断地轮询服务器以从中获取新数据。我很困惑以固定间隔运行的异步任务或服务运行是后台是更好的选择。线程只会在应用程序运行时运行
5 回答
你已经对你的问题有了一些答案,但我认为值得总结......
你需要什么
当您想要运行一段需要一些时间才能完成的代码时,您应该始终在与 UI 线程不同的线程中运行它。
您可以通过两种方式实现这一目标:
使用Thread
:
这是最简单的一种,如果您不需要从新线程到 UI 线程的大量通信。如果您需要通信,您可能必须使用 aHandler
来完成它。
使用AsyncTask
:
也在一个单独的线程中运行,并且已经实现了一些与 UI 线程的通信通道。因此,如果您需要将此通信返回到 UI,则此选项更为可取。
你不需要的东西
Service
这主要用于在您退出主应用程序后保持一些代码运行,并且它将在 UI 线程中运行,除非您使用上述选项生成一个新线程。你说你的线程应该在你退出应用程序时终止,所以这不是你需要的。
IntentService
这可以通过一个外部事件(即BroadcastReceiver
)来激活,该事件可以启动您定义的一段代码,即使您的应用程序没有运行。再一次,根据您的要求,这不是您想要的。
问候。
Android 服务不在后台线程中。
因此,您应该运行一个服务,每次您想轮询时都会启动一个 ASyncTask。
请注意,服务与其他应用程序对象一样,在其托管进程的主线程中运行。这意味着,如果您的服务要执行任何 CPU 密集型(例如 MP3 播放)或阻塞(例如网络)操作,它应该生成自己的线程来完成这项工作。更多信息可以在进程和线程中找到。IntentService 类可作为 Service 的标准实现使用,它有自己的线程来安排要完成的工作。
如果你想“不断地轮询”,asyncTask 就不行了。当您的应用程序被 Android 停止时,任务就会停止。正如 Blundell 已经指出的那样,服务本身也不会这样做。Service 在主线程中运行,您不想在主线程中进行轮询。有两种方法可以做到这一点:您创建一个服务,它产生自己的线程来执行您希望它执行的操作,或者您让它安排在 AsyncTask 或单独线程中执行的轮询。我尽量不在我的应用程序中进行轮询,但如果必须,在您的服务中创建一个执行轮询的特殊线程对我来说似乎是最好的。
根据您的应用程序所做的事情和轮询的内容,您可以给单独的线程一个较低的优先级,这样它就不会妨碍其他处理。
Service
不应相提并论AsyncTask
。我猜你很可能是指这里 -尽管有通用名称,但这与IntentService
略有不同。Service
至于定期提取,我会坚持使用经常性警报(使用AlarmManager
)和(很可能)使用IntentService
来进行提取。
这里有AsyncTask 基础知识和一些教程 这里有IntentService 基础知识和教程
请注意,IntentService
作业是按设计排队的,而AsyncTasks
可以完全并行运行。但是请注意与较新 API 中的 AsyncTask 处理相关的回归。没什么大不了的,因为解决方法只是增加了几行代码,但是值得知道这一点。
编辑
许多关于 AsyncTask 生命周期与 Activity 生命周期联系在一起的误解浮出水面。这是错误的。AsyncTask 独立于 Activity。Finishing Activity 不会对任何 AsyncTask 执行任何操作,除非您通过代码从 onDestroy() 中清除它们。然而,如果一个活动的进程在后台被杀死,那么 AsyncTask 也将被杀死,作为被杀死的整个进程的一部分
线程只会在应用程序运行时运行
然后AsyncTask
将是最简单的解决方案。publishProgress()
使用后台线程定期向应用线程发送数据。Thread.sleep()
使用in设置所需的间隔doInBackground()
。另外,请确保您在 Activity 方法中开始一个新任务onResume()
,并在 Activity 方法中结束此任务onPause()
。
例子:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
@Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
@Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}