我正在尝试创建一个经常更改TextView值的应用小部件 - 秒表小部件。为此,我使用runnable,我在处理程序中启动以更新值,然后将textview设置为这些值。出于某种原因,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方法,我应该点击按钮更新textview:
@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);
}
这与我用来为实际应用程序更新它的代码相同,只有这样才能修改app小部件。我知道时间正在更新 - 如果我在日志中显示它,它会正确更新时间。我也知道如果我在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,也不能通过从intent中获取额外内容来更改它们在appwidget类中。由于某种原因,所有内容都返回空白/ null - 意图附加内容或remoteViews,进出服务。而且我意识到这对电池来说可能不是很好或非常有效,但是让我感到烦恼的是我根本无法更新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);
答案 0 :(得分:1)
您只需拨打AppWidgetManager.updateAppWidget(widget, remoteViews)
一次。每次更新小部件时都需要调用它。
答案 1 :(得分:1)
为什么你这么复杂(和cpu密集型)?
只需设置一个服务,在启动时以您选择的间隔设置AlarmManager。 让AlarmManager向您的AppWidgetProvider类发送广播并在那里捕获该意图。
现在只需更新您的小部件。