我已经创建了一个前台服务,它可以使用一段时间后可以运行的可运行对象。它运行了很长时间。起初我将这段代码放入服务中:
private final Handler handler = new Handler();
...
...
public int onStartCommand(...
handler.postDelayed(sendUpdatesToUI, 50);
...
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
try {
DBAdapter DB = new DBAdapter(MyService.this);
DB.open();
DB.insertData(System.currentTimeMillis(), "",
cronometro.tiempo_original, 0) ;
DB.close();
} catch (Exception e) {
Toast.makeText(MyService.this, e.toString(),Toast.LENGTH_LONG).show();
}
SendInfo();
handler.postDelayed(this, 300000);
}
};
但是上面的代码有一个问题:处理程序在UI线程中运行,因此如果UI活动不在内存中,则后延迟函数不起作用,因为工作线程不再处于活动状态。所以我更改了代码以在特定于活动的调度程序(处理程序)之间使用系统sheduler。现在代码看起来像这样:
private final ScheduledExecutorService schedulerService = Executors.newScheduledThreadPool(1);
private ScheduledFuture scheduleFuture;
...
...
public int onStartCommand(...
scheduleFuture = schedulerService.schedule(sendUpdatesToUI,50, TimeUnit.MILLISECONDS);
...
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
try {
DBAdapter DB = new DBAdapter(MyService.this);
DB.open();
DB.insertData(System.currentTimeMillis(), "",
cronometro.tiempo_original, 0) ;
DB.close();
} catch (Exception e) {
Toast.makeText(MyService.this, e.toString(),Toast.LENGTH_LONG).show();
}
SendInfo();
scheduleFuture = schedulerService.schedule(sendUpdatesToUI,300000,TimeUnit.MILLISECONDS);
}
};
第二个代码是为长期服务执行此操作的正确方法,该服务不会出现在前面。 正如您所看到的,代码执行相同操作,但它避免了使用处理程序的问题,该处理程序依赖于主UI线程。
如果我评论两者的SQL代码,只要主要活动位于顶部,它们就会运行完美。但如果我不评论sql代码,第二个示例挂起并且不运行。它在sqlcode处停止,因为DatabaseHelper需要有效的上下文,并且由于执行程序是系统上下文,因此它不会运行。我放在DBAdapter(上下文)中的任何上下文(如getApplicationContext(),getBaseContext()或MyService.this)都不起作用。
有谁知道如何为第二个例子提供有效的上下文?
答案 0 :(得分:2)
但上面的代码有一个问题:处理程序在UI线程中运行,因此如果UI活动不在内存中,则后延迟函数不起作用,因为工作线程不再处于活动状态。
服务与活动共享相同的主应用程序线程(“UI线程”)。 AFAIK,无论UI状态如何,都应“工作”。由于其他原因,这是一个糟糕的实现(见下文)。
第二个代码是为长期服务执行此操作的正确方法,该服务不会在前面。
这比第一次实施更好。两者都很差。请使用AlarmManager
和IntentService
,这样您就不会在服务五分钟内没有做任何事情时浪费用户的资源。
它在sqlcode处停止,因为DatabaseHelper需要一个有效的上下文,并且由于执行程序是一个系统上下文,它不会运行。
你的说法毫无意义。只要Service
正在运行,您就使用Context
对象,该对象是有效的Service
。 ScheduledExecutorService
是普通的Java对象,无法提供Context
。我不知道你认为“系统环境”是什么。
我放入DBAdapter(上下文)的任何上下文(如getApplicationContext(),getBaseContext()或MyService.this)都不起作用。
然后你还有其他一些问题,例如多线程访问数据库的同步/死锁问题,或者你的Service
被破坏(因此,你泄露了这个后台线程)。
如果您使用AlarmManager
和IntentService
,并使用所有组件之间共享的onHandleIntent()
在SQLiteOpenHelper
中执行数据库I / O(此服务)和你的活动),你应该有更好的结果。