2010-12-10 5 views
2

GameLogic -singleton의 업데이트 메소드를 호출하는 서비스가 있습니다. GameLogic은 일부 상태 업데이트가 필요하다고 결정할 수 있습니다. 이 경우 수신자에게 StatusUpdateEvent에 대해 알립니다.onDelete가 계속 듣고 난 후에 android widget이

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. 
} 

그러나 문제는 지금 : 내가 홈 화면에 위젯을 추가, everythings 미세 listeneres는 내가 StatusUpdateEvent에 귀를 기울여야 위젯을

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

등 자신의보기를 업데이트 . 그런 다음 홈 화면에서 위젯을 삭제하면 onDelete Toast가 표시되지만 이후에는 여전히 해당 Log 항목이 표시됩니다. ProjectWidget onStatusUpdate.

그래서 수신기가 제거되지 않습니다. 왜? 어떻게해야합니까?

감사합니다.

답변

3

그래서 수신기가 제거되지 않습니다. 왜? 어떻게해야합니까?

보유하고있는 것은 메모리 누수입니다.

AppWidgetProvider은 일시적인 개체입니다. onUpdate() 또는 다른 앱 위젯 라이프 사이클 메소드를 처리 할 수있을만큼 오래 지속 된 다음 사라집니다.

결코 결코 결코 결코 는 당신이로 정적 컨텍스트에 등록하는 것과 같이 살아있는 이상이보다 AppWidgetProvider을하려고하지 않는다. AppWidgetProvider은 가비지 수집되지 않으므로 메모리가 누수됩니다.

removeStatusUpdateListener()을 호출 할 때 addStatusUpdateListener()과 (와) 다른 AppWidgetProvider 인스턴스가 있습니다. 따라서 remove 연산은 no-op (등록되지 않은 무언가를 제거함)이며, 원래 수신기는 영원히 그곳에있게됩니다.

GameLogic 또는 앱 위젯을 직접 업데이트 하시겠습니까? RemoteViews.

+0

감사합니다. 저는 AppWidgetProvider의 과도 현상을 인식하지 못했습니다! 나는 지금 서비스에서 그것을하고있다 : \t 컨텍스트 컨텍스트 = this; \t AppWidgetManager appWidgetManager = AppWidgetManager.getInstance (context); \t RemoteViews remoteViews = 새로운 RemoteViews (context.getPackageName(), R.layout.widget_2x1); \t ComponentName thisWidget = 새 ComponentName (context, MyWidget.class); \t remoteViews.setTextViewText (R.id.my_text_view, "myText"+ System.currentTimeMillis()); \t appWidgetManager.updateAppWidget (thisWidget, remoteViews); – Stuck

+0

@ Stuck : 그래, 괜찮아. 'AppWidgetProvider'는 실제로는 라이프 사이클 이벤트에 대한 이벤트 핸들러 일뿐입니다. 당신은 어디서든 앱 위젯'RemoteViews'를 업데이트 할 수 있습니다. – CommonsWare

관련 문제