如何修复更新小部件的 ANR 错误

Posted

技术标签:

【中文标题】如何修复更新小部件的 ANR 错误【英文标题】:How to fix ANR error for updating widgets 【发布时间】:2018-05-23 14:14:28 【问题描述】:

我有一个 JobScheduler 服务触发更新小部件 UI。

@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());
    

我在广播意图 act=.....UPDATE_WIDGET

时收到 ANR 错误

由于我无法在我的设备上复制,我不得不猜测解决方案是什么。

解决方案 #1 我可以传递将减少 UI 运行时的值,而不是保存到 SharedPreferences 并从 SharedPreferences 中读取。这个我可以马上做出改变。

解决方案 #2 我应该调用一个广播并传递所有小部件 ID,而不是循环每个小部件 ID 并调用每个小部件 ID 的广播?不会让 onReceive() 花费更长的时间来执行吗? (因为它必须更新所有小部件)。

解决方案 #2 是我不确定的。这种改变会有帮助吗?还是导致 ANR 更频繁地发生?

【问题讨论】:

问题解决了吗?我在某些三星设备上遇到了同样的问题。我认为这是邪恶的电池管理员。 【参考方案1】:

回答我自己的问题。

解决方案 #1 通过意图传递数据值以避免从 SharedPreferences 加载数据和/或从 WorkerThread 加载 SharedPreferences 消除了 ANR 错误。

我已经尝试了解决方案 #2,但我不确定它是否有助于消除 ANR。

【讨论】:

以上是关于如何修复更新小部件的 ANR 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何将旧的小部件迁移到新的小部件

一旦视图更改,颤动数字时钟小部件就会导致错误

如何修复非空字符串必须提供给文本小部件?

小部件更新的 RemoteViews 超出最大位图内存使用错误

小部件不更新视图并且也没有显示错误

如何在更新父有状态小部件时更新子有状态小部件