2012-08-08 45 views
2

我正在嘗試使應用程序Widget頻繁地更改TextView值 - 秒錶小部件。爲了做到這一點,我使用了一個runnable,我從一個處理程序開始更新值,然後將textview設置爲這些值。出於某種原因,textview不會更新。一切工作正常,textview只是不會更新。Android:使用處理程序更新應用程序Widget TextView並可運行

下面是處理程序和可運行代碼:

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); 
} 

這是我用它來更新它的實際應用,其工作原理相同的代碼,只有這個被修改的應用小部件。我知道時間正在更新 - 如果我在日誌中顯示它,它會正確更新時間。我也知道,如果我直接在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更新。

我知道這是相當草率的,我嘗試了幾種不同的技術來使它工作,但沒有一個能夠工作,我也沒有清理舊技術。它無法直接更改remoteView,也無法通過從意圖中獲取額外內容在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); 

回答

1

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

+0

我是個白癡。我不知道我從來沒有想過這件事。謝謝,它現在有效。 – NSchock 2012-08-14 02:01:40

1

你爲什麼這麼複雜(和CPU密集型)?

只需在啓動時按照您選擇的時間間隔設置一個設置AlarmManager的服務。 讓AlarmManager向您的AppWidgetProvider類發送一個廣播,並在那裏捕獲該意圖。

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