2017-09-12 6 views
0

Mon widget est un fond blanc qui permute entre deux couleurs avec un délai de 333 ms entre chaque commutateur. Il fonctionne bien au début, mais après 158 commutateurs, il arrête de changer de couleur. La chose est, je ne compte pas sur onUpdate. Tout est dans une boucle while infinie qui est d'abord appelée lorsque je mets le widget sur mon écran d'accueil. Qu'est-ce qui pourrait l'amener à arrêter la commutation après 158 commutateurs? Est-ce que la modification de la couleur de fond comme celle-ci pourrait être trop coûteuse, et le système d'exploitation désactive mon widget?Qu'est-ce qui fait que la boucle infinie de mon widget ne fonctionne plus?

ColorSwitchWidget.java:

public class ColorSwitchWidget extends AppWidgetProvider { 

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { 

     RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.color_switch_widget); 

     boolean lightOn = true; 

     while(true){ 
      try{ 
       Thread.sleep(333); 
      } catch(InterruptedException e){ 
      } 

      if (lightOn) { 
       views.setInt(R.id.RelativeLayout1, "setBackgroundColor", Color.argb(150, 255, 248, 231)); //color 1 
       lightOn = false; 
       appWidgetManager.updateAppWidget(appWidgetId, views); 
      } else { 
       views.setInt(R.id.RelativeLayout1, "setBackgroundColor", Color.argb(220, 255, 248, 231)); //color 2 
       lightOn = true; 
       appWidgetManager.updateAppWidget(appWidgetId, views); 
      } 
     } 
    } 

    @Override 
    public void onUpdate(Context context, AppWidgetManager, appWidgetManager, int[] appWidgetIds) { 
     for (int appWidgetId : appWidgetIds) { 
      updateAppWidget(context, appWidgetManager, appWidgetId); 
     } 
    } 

    @Override 
    public void onEnabled(Context context) { 
    } 

    @Override 
    public void onDisabled(Context context) { 
    } 
} 

color_switch_widget_info.xml:

<?xml version="1.0" encoding="utf-8"?> 
<appwidget-provider 
xmlns:android="http://schemas.android.com/apk/res/android" 
    android:initialKeyguardLayout="@layout/color_switch_widget" 
    android:initialLayout="@layout/color_switch_widget" 
    android:minHeight="40dp" 
    android:minWidth="40dp" 
    android:previewImage="@drawable/widget_icon_blink" 
    android:resizeMode="horizontal|vertical" 
    android:updatePeriodMillis="1800000" 
    android:widgetCategory="home_screen"></appwidget-provider> 

Le widget fonctionne ... mais pas pour très longtemps. La boucle infinie est-elle un mauvais choix?

Modifier: une solution de contournement qui n'utilise pas Thread.sleep() a été trouvée. Je ne suis pas sûr si cela va causer des problèmes ou des problèmes de mémoire, mais cela semble fonctionner pour l'instant.

final Handler myHandler = new Handler(); 
final Runnable blinkRunnable = new Runnable(){ 
    int lightOff = true; 
    public void run(){ 
     if(lightOff){ 
      lightOff = false; 
      views.setInt(R.id.RelativeLayout1, "setBackgroundColor", Color.argb(220, 255, 248, 231)); //light "on" 
      appWidgetManager.updateAppWidget(appWidgetId, views); 
      myHandler.postDelayed(this, 333); 
     } else{ 
      lightOff = true; 
      views.setInt(R.id.RelativeLayout1, "setBackgroundColor", Color.argb(150, 255, 248, 231)); //light "off" 
      appWidgetManager.updateAppWidget(appWidgetId, views); 
      myHandler.postDelayed(this, 333); 
     } 
    } 
}; 

//start the loop 
myHandler.post(blinkRunnable); 

Répondre

0

Le problème ici est le fait que vous ne l'exécutez pas sur un fil personnalisé. La méthode est appelée à partir du thread principal, et lorsque vous mettez en pause le thread principal (Thread.sleep()) Android pense que l'application ne répond pas.

Utilisez un nouveau fil à la place en créant une nouvelle classe et de le laisser prolonger cette discussion

+0

viens de découvrir à quel point il est à Thread.sleep() ici ... J'ai aussi essayé de mettre Thread.sleep (1000) dans son propre thread, mais il ne semble pas retarder le code setBackground. Ma conjecture est que l'autre thread a dormi pendant que le fil principal continuait à avancer. – Kawaii

+0

Les threads secondaires exécutent leur propre thread, donc bien sûr, le thread principal continue à fonctionner. C'est le but. Bloquez le thread principal et votre application recevra ANR et risque de tomber en panne. Les opérations lourdes doivent toujours être effectuées sur un thread qui n'est pas le thread principal – Zoe