2011-07-11 35 views
4

我有一個小部件,每當配置發生變化時(例如屏幕方向),以及手機解鎖時都會自動更新。該過程涉及爲我的小部件上的按鈕設置onClick處理程序。這很好,但我發現有一個用例導致我的應用程序不響應onClick事件。這種特殊情況是啓動程序自動重新啓動的時間。在啓動器重啓時未更新的小工具

有沒有辦法檢測啓動程序何時重新啓動,所以我可以手動更新我的小部件?還是有另一種方法來確保onClick處理程序不會丟失?

+0

可能重複[啓動重啓後無法正常工作的onClick意圖。(http://stackoverflow.com/questions/4909886/onclick-intents-not-working-after-launcher-restart) – Macarse

回答

10

原來我是垃圾郵件new RemoteViews()當我應該只是調用它來產生視圖,然後在需要時提到一個實例。在我的解決方案中,我有一個存儲這個RemoteView實例的類變量,以及一個訪問它的getter。

+1

這個問題似乎即使在你提出的修正之後仍然堅持。我認爲這與[** Issue 28216 **](http://code.google.com/p/android/issues/detail?id=28216)相同。 –

+0

這非常含糊。你能否提供更多的細節? 「叫了一次」......這是什麼意思?對於每次更新迭代,您創建一個RemoteViews實例,或者創建一次並保留參考(例如,在服務中)。 –

+0

這工作很好,謝謝! Ofc,像往常一樣,Android文檔是廢話。我在各個地方看了一個正確的答案,這是唯一有效的答案。 @CleverCoder是的,保持你只創建一次的單個實例。因此,在Widget的onUpdate中,如果您的引用爲null,則只創建remoteViews對象! – Radu

0

@Glitch的提案可能不適用於某些情況,特別是與ListView的應用程序窗口小部件。這是因爲ListView會變得非常緩慢(嘗試滾動ListView),因爲appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id)已被多次調用。

我的猜測是,單個RemoteView實例會將其所有執行的指令保留在列表中。隨着時間的推移,指令列表將會增長。每次appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id),大指令列表都會重新執行。

我建議的解決方案如下。但是,我相信它只能在某些設備上工作,因爲在啓動程序重新啓動期間,並非所有設備都會收到相同的廣播消息。的

@SuppressLint("NewApi") 
@Override 
public void onReceive(Context context, Intent intent) { 
    final String action = intent.getAction(); 

    if (action.equals("com.sec.android.widgetapp.APPWIDGET_RESIZE")) { 
     // http://stackoverflow.com/questions/17396045/how-to-catch-widget-size-changes-on-devices-where-onappwidgetoptionschanged-not 
     handleTouchWiz(context, intent); 

     // Possible launcher restart. 
     handleLauncherRestart(context, intent); 
    } else if (action.equals("android.appwidget.action.APPWIDGET_UPDATE_OPTIONS")) { 

     // Possible launcher restart.    
     handleLauncherRestart(context, intent); 
    } 

    super.onReceive(context, intent); 
} 

private void handleLauncherRestart(Context context, Intent intent) { 
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 
    int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 
      AppWidgetManager.INVALID_APPWIDGET_ID); 
    updateAppWidget(context, appWidgetManager, appWidgetId); 
} 

private void handleTouchWiz(Context context, Intent intent) { 
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 

    int appWidgetId = intent.getIntExtra("widgetId", 0); 
    int widgetSpanX = intent.getIntExtra("widgetspanx", 0); 
    int widgetSpanY = intent.getIntExtra("widgetspany", 0); 

    if (appWidgetId > 0 && widgetSpanX > 0 && widgetSpanY > 0) { 
     Bundle newOptions = new Bundle(); 
     // We have to convert these numbers for future use 
     // http://stackoverflow.com/questions/10008521/appwidget-size-calculation 
     if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
      newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, widgetSpanY * 74 - 2); 
      newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, widgetSpanX * 74 - 2); 

     } else { 
      newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, widgetSpanY * 70 - 30); 
      newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, widgetSpanX * 70 - 30); 
     } 

     onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); 
    } 
}