2

我正在尝试制作一个经常更改 TextView 值的应用小部件——一个秒表小部件。为此,我使用在处理程序中启动的可运行对象来更新值,然后将 textview 设置为这些值。出于某种原因,文本视图并没有更新。一切正常,文本视图不会更新。

以下是 Handler 和 Runnable 的代码:

RemoteViews remoteViews;
long sStart, elapsedTime;
private final int REFRESH_RATE = 100;
private Handler sHandler = new Handler();
private Runnable startStopwatch = new Runnable() {
    @Override
    public void run() {
        final long start = sStart;
        elapsedTime = System.currentTimeMillis() - start;
        updateStopwatch(elapsedTime);
        sHandler.postDelayed(this, REFRESH_RATE);
    }
};


private void updateStopwatch(long time) {
    int seconds = (int) time / 1000;
    int minutes = seconds / 60;
    int hours = minutes / 60;
    long millis = time % 1000;
    seconds = seconds % 60;

    remoteViews.setTextViewText(R.id.tvStopwatchWidget, String.format("%d : %02d : %02d", hours, minutes, seconds));
    remoteViews.setTextViewText(R.id.tvStopwatchMillisWidget, String.format(". %03d", millis));

}

我在 onUpdate 方法中设置了所有内容,一切正常。onReceive 方法,我应该在单击按钮时更新文本视图,是这样的:

    @Override
public void onReceive(Context context, Intent intent) {
    remoteViews = new RemoteViews(context.getPackageName(), R.layout.stopwatch_widget_layout);
    if (intent.getAction().equals(ACTION_STOPWATCH_WIDGET_START)) {
        if (sStart == 0L) {
            sStart = System.currentTimeMillis();
        } else {
            sStart = System.currentTimeMillis() - elapsedTime;
        }
        sHandler.removeCallbacks(startStopwatch);
        sHandler.postDelayed(startStopwatch, REFRESH_RATE);
    }
    ComponentName widget = new ComponentName(context, StopwatchWidgetProvider.class);
    AppWidgetManager.getInstance(context).updateAppWidget(widget, remoteViews);
    super.onReceive(context, intent);
}

这是我用来为实际应用程序更新它的相同代码,它有效,只是针对应用程序小部件进行了修改。我知道时间正在正确更新——如果我在日志中显示它,它会正确更新时间。如果我直接在 onReceive 方法中更改它,我也知道 textview 会正确更改。一切似乎都在工作,但由于某种原因,它不会更新它尝试在 Runnable 中的时间,所以我真的不知道如何解决这个问题。

我也尝试过使用服务,但效果并没有更好。它的代码是:

public class SWStartService extends Service {

RemoteViews remoteViews;
long sStart = 0;
long elapsedTime;
private final int REFRESH_RATE = 100;
private Handler sHandler = new Handler();
private Runnable startStopwatch = new Runnable() {
    @Override
    public void run() {
        final long start = sStart;
        elapsedTime = System.currentTimeMillis() - start;
        updateStopwatch(elapsedTime);
        sHandler.postDelayed(this, REFRESH_RATE);
    }
};
String sMain, sMillis;

private void updateStopwatch(long time) {
    int seconds = (int) time / 1000;
    int minutes = seconds / 60;
    int hours = minutes / 60;
    long millis = time % 1000;
    seconds = seconds % 60;

    remoteViews.setTextViewText(R.id.tvStopwatchWidget, String.format("%d : %02d : %02d", hours, minutes, seconds));
    remoteViews.setTextViewText(R.id.tvStopwatchMillisWidget, String.format(". %03d", millis));
    Intent i1 = new Intent(getApplicationContext(), SWStartService.class);
    sMain = String.format("%d : %02d : %02d", hours, minutes, seconds);
    sMillis = String.format(". %03d", millis);
    //  Log.d("TEST TIME", String.format("%d : %02d : %02d . %03d", hours, minutes, seconds, millis));
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.stopwatch_widget_layout);
    if (sStart == 0L) {
        sStart = System.currentTimeMillis();
    } else {
        sStart = System.currentTimeMillis() - elapsedTime;
    }
    sHandler.removeCallbacks(startStopwatch);
    sHandler.postDelayed(startStopwatch, 100);
    intent.putExtra("sMainWidget", sMain);
    intent.putExtra("sMillisWidget", sMillis);

    sendBroadcast(intent);
    return START_REDELIVER_INTENT;
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

该服务在 onReceive 方法中调用,如下所示:

Intent intent1 = new Intent(context, SWStartService.class);
context.startService(intent1);

我尝试了其他一些技术来启动服务,但我仍然无法更新 TextView。

我知道这很草率,我尝试了几种不同的技术来让它工作,但都没有奏效,我也没有清理旧的技术。它不适用于直接更改 remoteViews,或者通过从意图中获取额外内容来更改 appwidget 类中的它们。一切都只是返回空白/空——出于某种原因进入或退出服务的意图附加或远程视图。而且我意识到这对电池来说可能不是很好,也可能不是很有效,但让我感到困扰的是,我什至根本无法更新 TextView。

有什么建议么?

编辑:有人可能想要解决方案,所以在这里:

//Global Variables
ComponentName widget;
AppWidgetManager awManager;

//Set them up in onReceive method
    remoteViews = new RemoteViews(context.getPackageName(), R.layout.stopwatch_widget_layout);
    widget = new ComponentName(context, StopwatchWidgetProvider.class);
    awManager = AppWidgetManager.getInstance(context);
    if (intent.getAction().equals(ACTION_STOPWATCH_WIDGET_START)) {
        //showStopButton();
        if (sStart == 0) {
            sStart = System.currentTimeMillis();
        } else {
            sStart = System.currentTimeMillis() - elapsedTime;
        }
        sHandler.removeCallbacks(startStopwatch);
        sHandler.postDelayed(startStopwatch, REFRESH_RATE);
    }
    awManager.updateAppWidget(widget, remoteViews);
    super.onReceive(context, intent);

//update appwidget in runnable
        final long start = sStart;
        elapsedTime = System.currentTimeMillis() - start;
        updateStopwatch(elapsedTime);
        sHandler.postDelayed(this, REFRESH_RATE);
        awManager.updateAppWidget(widget, remoteViews);
4

2 回答 2

1

你只调用AppWidgetManager.updateAppWidget(widget, remoteViews)一次。每次更新小部件时都需要调用它。

于 2012-08-13T08:28:15.963 回答
1

为什么你做的这么复杂(而且 CPU 密集型)?

只需设置一个服务,在启动时设置一个具有您选择的时间间隔的 AlarmManager。让 AlarmManager 向您的 AppWidgetProvider-class 发送广播并在那里捕获该意图。

现在只需更新您的小部件。

于 2012-11-01T09:45:24.430 回答