2010-12-10 11 views
2

私はGameLogic -singletonでいくつかの更新メソッドを呼び出すサービスを持っています。 GameLogicは、ステータス更新が必要であると判断することがあります。この場合、リスナーにStatusUpdateEventについて通知します。onDeleteの後にアンドロイドウィジェットをお待ちください

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

しかし、問題は今:私はホームスクリーンにウィジェットを追加 、何もかも細かい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が表示されますが、その後もログエントリ:ProjectWidget onStatusUpdateが表示されます。

したがって、リスナーは削除されません。なぜですか?どうすればいいの?

ありがとうございます!

答えて

3

したがって、リスナーは削除されません。なぜですか?どうすればいいの?

メモリリークがあります。

AppWidgetProviderは一時オブジェクトです。 onUpdate()やその他のアプリウィジェットのライフサイクルメソッドを処理するのに十分な時間が経過してから消えます。

決して決して決して決して決して決しては、あなたがそうであるように、静的コンテキストでそれを登録することなどによって、AppWidgetProviderライブこれより長い持ってしてみてください。 AppWidgetProviderはガベージコレクションされないため、メモリがリークしています。

removeStatusUpdateListener()を呼び出すときは、addStatusUpdateListener()で使用したものとは異なるAppWidgetProviderインスタンスがあります。したがって、削除操作はノーオペレーション(登録されていないものを削除しています)であり、元のリスナーは永遠にそこにとどまります。

あなたのGameLogicなどは、アプリウィジェットRemoteViewsを直接更新してください。

+0

ありがとうございました。私はAppWidgetProviderの過渡性を認識していませんでした。私は今サービスからそれをやっています: \tコンテキストコンテキスト= this; \t AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); \t RemoteViews remoteViews =新しいRemoteViews(context.getPackageName()、R.layout.widget_2x1); \tコンポーネント名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

関連する問題