Как исправить ошибку ANR для обновления виджетов

У меня есть служба JobScheduler, запускающая обновление пользовательского интерфейса виджета.

@Override
    public boolean onStartJob(final JobParameters params) {
        //Offloading work to a new thread.
        new Thread(() -> {
            try {
                // Here we receive updated data and store to SharedPreferences 
                ...
                MyWidgetProvider.updateWidgets(getApplicationContext());
            } catch (Exception e) {
                Log.e(TAG, "onStartJob: " + e.getMessage());
            } finally {
                jobFinished(params, false);
            }
        }).start();
        return true;
    }

Мой AppWidgetProvider:

protected static void updateWidget(Context context) {
    try {
        ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class);
        int[] appWidgetIds = AppWidgetManager.getInstance(context.getApplicationContext()).getAppWidgetIds(thisWidget);
        if (appWidgetIds != null) {
            if (appWidgetIds.length > 0) {
                for (int appWidgetId : appWidgetIds) {
                    try {
                        Intent intent = new Intent(context, MyWidgetProvider.class);

                        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                        intent.setAction(UPDATE_WIDGET);
                        context.sendBroadcast(intent);
                    } catch (Exception e) {
                    }
                }
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "error" + e.getMessage());
    }
}


@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    try {
        Bundle extras = intent.getExtras();
        String action = intent.getAction();
        if (extras != null && !TextUtils.isEmpty(action)) {
            int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                if (action.equals(UPDATE_WIDGET)) {

                    RemoteViews remoteViews = getRemoteView(context);
                    // Here read from the SharedPreferences and updates the remoteViews
                    ....

                    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                    appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);
                } 
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "onReceive() error: " + e.getMessage());
    }
}

Я получаю ошибки ANR при трансляции намерения {act=.....UPDATE_WIDGET}

Поскольку я не могу воспроизвести на своем устройстве, я должен угадать, каким будет решение.

Решение №1 Вместо сохранения в SharedPreferences и чтения из SharedPreferences я могу передать значение, которое уменьшит время выполнения пользовательского интерфейса. Это я могу внести изменения прямо сейчас.

Решение № 2. Вместо того, чтобы зацикливать идентификатор виджета и вызывать широковещательную рассылку для каждого идентификатора виджета, следует ли вызвать одну широковещательную рассылку и передать все идентификаторы виджетов? Разве это не заставит onReceive() выполняться дольше? (поскольку он должен обновить все виджеты).

Решение № 2 - это то, в чем я не уверен. Будет ли это изменение полезным? или заставляет ANR происходить чаще?


person jclova    schedule 23.05.2018    source источник


Ответы (1)


Отвечая на мой собственный вопрос.

Решение № 1 Либо передача значения данных через намерение, чтобы избежать загрузки данных из SharedPreferences, и/или загрузка SharedPreferences из WorkerThread устранила ошибки ANR.

Я попробовал решение № 2 и не уверен, помогло ли оно устранить ANR или нет.

person jclova    schedule 05.07.2018