2010-12-10 18 views
2

我有一个服务调用GameLogic -singleton中的某些更新方法。 GameLogic可能会决定需要进行一些状态更新。在这种情况下,它通知其听众关于StatusUpdateEvent。该listeneres然后更新自己的观点等onDelete仍在监听之后的Android小部件

public class GameLogic { 
    // ... attributes ... 
    private static GameLogic instance = null; 
    private GameLogic() { 
     // singleton pattern 
    } 
    public static synchronized GameLogic getInstance() { 
     if (instance == null) { 
      instance = new GameLogic(); 
     } 
     return instance; 
    } 
    public void checkStatus() { 
     // called by service 
     // ... some checks 
     notifyStatusUpdate(new StatusUpdateEvent()); 
    } 
    public void addStatusUpdateListener(StatusUpdateListener listener) { 
     if (!listeners.contains(listener)) { 
      listeners.add(listener); 
     } 
    } 
    public void removeStatusUpdateListener(StatusUpdateListener listener) { 
     listeners.remove(listener); 
    } 
    protected synchronized void notifyStatusUpdate(StatusUpdateEvent event) { 
     for (StatusUpdateListener l : listeners) { 
      l.onStatusUpdate(event); 
     } 
    } 
} 

我应该听StatusUpdateEvent一个小部件:

public class ProjectWidget extends AppWidgetProvider implements StatusUpdateListener { 
    // ... attributes ... 
    @Override 
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 
     this.context = context; 
     this.appWidgetManager = appWidgetManager; 
     this.remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_2x1); 
     this.thisWidget = new ComponentName(context, ProjectWidget.class); 

     GameLogic.getInstance().addStatusUpdateListener(this); 
    } 

    @Override 
    public void onDeleted(Context context, int[] appWidgetIds) { 
     Toast.makeText(context, "onDeleted", Toast.LENGTH_SHORT).show(); 
     GameLogic.getInstance().removeStatusUpdateListener(this); 
     super.onDeleted(context, appWidgetIds); 
    } 
    @Override 
    public void onStatusUpdate(StatusUpdateEvent e) { 
     android.util.Log.d("ProjectWidget", "onStatusUpdate"); 
     // here some class fields are updated like this.project = e.getProject(); 
     // ... 
     updateViews(); 
     appWidgetManager.updateAppWidget(thisWidget, remoteViews); 
    } 
    // ... updateViews() etc. 
} 

但现在的问题是: 我的小工具添加到主屏幕,万物精。然后,如果我从主屏幕上删除小部件,我会看到onDelete Toast,但之后我仍然可以看到日志条目:ProjectWidget onStatusUpdate。

因此,听众不会被删除..为什么?我该怎么做那些东西?

谢谢!

回答

3

所以听者不会被删除。为什么?我该怎么做那些东西?

你有什么是内存泄漏。

AppWidgetProvider是一个临时对象。它的寿命足够长,可以处理onUpdate()或其他应用部件生命周期方法,然后它就会消失。

永远永远永远永远永远从未尝试有一个AppWidgetProvider比这活得更长,如通过在静态情况下注册为你。你正在泄漏内存,因为AppWidgetProvider不会被垃圾收集。

当您致电removeStatusUpdateListener()时,您的AppWidgetProvider实例与您在addStatusUpdateListener()中使用的实例不同。因此,删除操作是一个无操作(你正在删除一些从未注册的东西),并且原始的听众将永远保持在那里。

让你的GameLogic或其他任何更新你的应用程序部件RemoteViews直接。

+0

谢谢,我没有意识到AppWidgetProvider的瞬变!我现在正在从服务: \t上下文context = this; \t AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); \t RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_2x1); \t ComponentName thisWidget = new ComponentName(context,MyWidget.class); \t remoteViews.setTextViewText(R.id.my_text_view,“myText”+ System.currentTimeMillis()); \t appWidgetManager.updateAppWidget(thisWidget,remoteViews); – Stuck 2010-12-10 20:22:34

+0

@Stuck:是的,这是一个很好的方法。 'AppWidgetProvider'实际上只是生命周期事件的事件处理程序 - 您可以从任何地方更新应用程序窗口'RemoteViews'。 – CommonsWare 2010-12-10 20:58:31