android长时间运行更新appwidget的操作

时间:2010-12-14 20:44:06

标签: android android-appwidget

我有一个小部件需要在onUpdate()中执行可能长时间运行的操作。只是直接执行操作导致ANR。为了解决这个问题,我的第一次尝试是在其中创建一个线程。我注意到在某些情况下小部件不会更新。我的猜测是,一旦onUpdate()退出,android可能会杀死进程以及未完成的线程。

我的下一次尝试是创建一个意向服务。小部件的onUpdate()只是启动intent服务,它直接完成工作并在完成后更新小部件。这很有用,但令我惊讶的是,onHandleIntent()似乎是单线程的。如果我有两个小部件,然后更新并启动意向服务,它们会按顺序更新...

这两个小部件的情况并不重要,但我只是想知道这种模式的最佳实践。

解决这两个小部件的情况我最后在点击其中任何一个时,用相同的数据更新所有小部件实例。例如,我执行一次长时间运行的过程并将结果应用于所有小部件实例。在我的场景中,这无关紧要,但对于许多小部件而言,重要的是不要这样做。

想法?

2 个答案:

答案 0 :(得分:3)

  

但令我惊讶的是,onHandleIntent()似乎是单线程的

  

如果我有两个小部件,然后更新并启动意向服务,它们会按顺序更新...

  

但我只是想知道这种模式的最佳做法。

你的IntentService是一个很好的解决方案,恕我直言。请记住,Android在速度较慢的CPU上运行,设备内存很少。并行运行大量线程通常不是一个好主意。

  

然后我开始在onHandleIntent()中启动一个线程,这需要一个唤醒锁定,它似乎变得太复杂了。

试试我的WakefulIntentService

答案 1 :(得分:0)

使onUpdate调用您自己的函数来循环访问小部件并更新它们。在循环之前执行异步任务。您将需要两个单独的操作,一个请求启动更新,另一个操作IntentService将广播以让小部件知道它们已完成。希望这会有所帮助。

    @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    updateWidget(context, appWidgetManager, appWidgetIds);
}

private void updateWidget(Context context){
    ComponentName widget = new ComponentName(context, MyWidget.class);
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    int[] appWidgetIds = appWidgetManager.getAppWidgetIds(widget);
    updateWidget(context, appWidgetManager, appWidgetIds);
}

private void updateWidget(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

    final boolean isEnabled = true; //took out code didn't want you to see
    // start intent service here
    for(int i = 0; i< appWidgetIds.length; i++){
        int appWidgetId = appWidgetIds[i];
        Intent intent = new Intent(isEnabled ? ACTION_TOGGLE_OFF : ACTION_TOGGLE_ON);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        views.setOnClickPendingIntent(R.id.widget , pi);
        views.setImageViewResource(R.id.widget_image, isEnabled? R.drawable.widget_on : R.drawable.widget_off);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}