服务计划未来和数据库冲突

时间:2011-12-17 15:18:44

标签: android database service scheduler

我已经创建了一个前台服务,它可以使用一段时间后可以运行的可运行对象。它运行了很长时间。起初我将这段代码放入服务中:

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)都不起作用。

有谁知道如何为第二个例子提供有效的上下文?

1 个答案:

答案 0 :(得分:2)

  

但上面的代码有一个问题:处理程序在UI线程中运行,因此如果UI活动不在内存中,则后延迟函数不起作用,因为工作线程不再处于活动状态。

服务与活动共享相同的主应用程序线程(“UI线程”)。 AFAIK,无论UI状态如何,都应“工作”。由于其他原因,这是一个糟糕的实现(见下文)。

  

第二个代码是为长期服务执行此操作的正确方法,该服务不会在前面。

这比第一次实施更好。两者都很差。请使用AlarmManagerIntentService,这样您就不会在服务五分钟内没有做任何事情时浪费用户的资源。

  

它在sqlcode处停止,因为DatabaseHelper需要一个有效的上下文,并且由于执行程序是一个系统上下文,它不会运行。

你的说法毫无意义。只要Service正在运行,您就使用Context对象,该对象是有效的ServiceScheduledExecutorService是普通的Java对象,无法提供Context。我不知道你认为“系统环境”是什么。

  

我放入DBAdapter(上下文)的任何上下文(如getApplicationContext(),getBaseContext()或MyService.this)都不起作用。

然后你还有其他一些问题,例如多线程访问数据库的同步/死锁问题,或者你的Service被破坏(因此,你泄露了这个后台线程)。

如果您使用AlarmManagerIntentService,并使用所有组件之间共享的onHandleIntent()SQLiteOpenHelper中执行数据库I / O(此服务)和你的活动),你应该有更好的结果。