【问题标题】:Chronometer doesn't update in app widget ListView应用程序小部件 ListView 中的 Chronometer 未更新
【发布时间】:2018-02-28 09:38:36
【问题描述】:

我有一个显示计时器的应用小部件。定时器可以启动、停止或恢复。

在 Android 8 上,计时器有时不计时 (50/50)。一些用户抱怨 Android 7 上的问题,但我不确定是否是同一个问题。在安装了 Android 6 的 Nexus 5 上一切正常。如果向下滚动列表视图(直到计时器不可见)并向上滚动 - 计时器开始计时。如果我在 ListView 上方再放一个 Chronometer 并启动 - 计时器运行良好

ActivitiesRemoteViewsFactory

public RemoteViews getViewAt(int position) {
...

    RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), getItemLayoutId());

    if (timeLog.getState() == TimeLog.TimeLogState.RUNNING) {          

        remoteViews.setChronometer(R.id.widget_timer,
                SystemClock.elapsedRealtime() - (duration * 1000 + System.currentTimeMillis() - timeLog.getStartDate().getTime()), null, true);
    } else {
        long timerValue = SystemClock.elapsedRealtime() - duration * 1000;
        remoteViews.setChronometer(R.id.widget_timer, timerValue, null, false);

    }

    return remoteViews;

AppWidgetProvider 的 onReceive 方法发送更新

public void onReceive(Context context, Intent intent) {   
   AppWidgetManager widgetManager = AppWidgetManager.getInstance(ctx);
    ...
   widgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_activities_list);
}

TargetSDK 是 25

更新 该问题也在主应用程序中重现。 listView 出了点问题,因为它在 RecyclerView 中运行良好。在https://github.com/zaplitny/WidgetIssue添加了重现问题的简单示例

【问题讨论】:

    标签: android listview widget chronometer


    【解决方案1】:

    Chronometer 小部件在 API 25 和 API 26 之间进行了更新,以防止更新不可见的计时器。 (这是我查看底层代码的最佳猜测。)具体来说,updateRunning() 方法已更改为考虑是否显示小部件。来自Chronometer.java

    对于 API 25:boolean running = mVisible && mStarted;

    对于 API 26:boolean running = mVisible && mStarted && isShown();

    isShown() 是您的问题的根源,它会阻止您的 Chronometers 被重用。对于 API 26+,重用的 Chronometers 似乎不会更新,当它们位于 ListView 中时。

    有几种方法可以解决这个问题。首先是不要重用Chronometers。在您的适配器的getView() 中,您可以使用以下代码:

    if (view == null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        view = LayoutInflater.from(getContext()).inflate(R.layout.widget_timer, parent, false);
    }
    

    使用此代码,您将始终创建新的Chronometers 并且永远不会重复使用它们。

    另一种方法是在小部件布局后调用chronometer.start()isShown() 将为真。将以下代码添加到getView()

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        chronometer.start();
    } else {
        view.post(new Runnable() {
            @Override
            public void run() {
                chronometer.start();
            }
        });
    } 
    

    任何一种方式都有效,还有其他方式。

    【讨论】:

    • @zaplitny IMO 这是Chronometer 中的一个错误。我提供的代码将解决这个问题。
    • 对不起,我删除了我之前的评论,因为我错过了您回答中的一些细节。我需要 AppWidget 和 AFAIK 中的计时器,你的解决方法是不可能的。但我可能错了
    • @zaplitny 我提供的代码适用于您提供的测试应用程序。不过,不知道AppWidget。我猜这是同样的问题。它仍然使用ListView,对吗?因此,应该检查 API 26+ 以抑制视图的重用。
    • @zaplitny 我明白你对AppWidget 的意思-ListView 是内部的,所以你没有像在测试应用程序中那样的访问权限。我仍然认为问题已经确定。问题是如何将修复导出到AppWidget
    • issuetracker.google.com/issues/74058586 在 2019 年 6 月 27 日上午 7:38 被标记为“不会修复(已过时)”... Cheticamp 选项仍然有效! :) 谢谢!
    【解决方案2】:

    在你的应用清单中添加这个:

     <!-- Widget Receiver -->
            <receiver android:name=".widgets.WidgetProvider">
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                </intent-filter>
    
                <meta-data
                    android:name="android.appwidget.provider"
                    android:resource="@xml/widget_provider" />
            </receiver>
    

    现在,当您想从应用程序更新小部件时,请调用:

                      try {
                            Intent intent = new Intent(ctxt, WidgetProvider.class);
                            intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
                            int ids[] = AppWidgetManager.getInstance(ctxt).getAppWidgetIds(new ComponentName(ctxt, WidgetProvider.class));
                            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
                            ctxt.sendBroadcast(intent);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
    

    我用它来更新我的小部件。 谢谢。

    【讨论】:

    • 问题不在于如何更新小部件。小部件内容更新良好,但 Chronometer 在 ListView 中无法按预期工作
    猜你喜欢
    • 2015-05-10
    • 2021-01-08
    • 1970-01-01
    • 2012-08-23
    • 2021-08-06
    • 1970-01-01
    • 2021-08-17
    • 2020-08-01
    • 1970-01-01
    相关资源
    最近更新 更多