8

で長時間実行される可能性のある操作を実行する必要があるウィジェットがありますonUpdate()。操作を直接実行するだけで、ANR が発生しました。これを解決するために、私の最初の試みはスレッドを作成することでした。ウィジェットが更新されない場合があることに気付きました。ここでの私の推測では、いったんonUpdate()終了すると、Android は未完了のスレッドとともにプロセスを強制終了する可能性があります。

私の次の試みは、インテント サービスを作成することでした。ウィジェットonUpdate()はインテント サービスを開始するだけで、直接作業を行い、完了時にウィジェットを更新します。これは機能しますが、驚いたことに、onHandleIntent()シングルスレッドのようです。2 つのウィジェットがあり、両方がインテント サービスを更新して開始した場合、それらは順次更新されます ...

2 つのウィジェットのケースはそれほど重要ではありませんが、このタイプのパターンのベスト プラクティスについて考えているだけです。

2 つのウィジェットのケースを解決するために、ウィジェット インスタンスのいずれかがクリックされるたびに、すべてのウィジェット インスタンスを同じデータで更新することになりました。たとえば、長期実行プロセスを 1 回実行し、その結果をすべてのウィジェット インスタンスに適用します。私のシナリオではこれは問題ではありませんが、多くのウィジェットではそうしないことが重要かもしれません。

考え?

4

2 に答える 2

3

しかし、驚いたことに、 onHandleIntent() はシングルスレッドのようです

はい。

2 つのウィジェットがあり、インテント サービスを更新して開始すると、それらは順次更新されます ...

はい。

しかし、このタイプのパターンのベストプラクティスについて疑問に思っています。

あなたIntentServiceは素晴らしい解決策でした、IMHO。Android は、RAM の少ないデバイスでは低速の CPU で実行されることに注意してください。多くのスレッドを並行して実行することは、一般的には良い考えではありません。

次に、ウェイクロックを必要とする onHandleIntent() でスレッドを開始しようとしていますが、複雑になりすぎているようです。

私の を試してみてくださいWakefulIntentService

于 2010-12-14T23:06:47.887 に答える
0

onUpdate で独自の関数を呼び出して、ウィジェットを循環させて更新します。サイクルの前に非同期タスクを実行します。2 つの別個のアクションが必要になります。1 つは更新の開始を求めるもので、もう 1 つ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);
    }
}
于 2010-12-14T20:53:42.513 に答える