4

シングルトンのクラスを作成しましたControllerが、同じアプリケーションの別のアクティビティでアクセスすると、そのオブジェクトが再作成されるという問題に直面しています。

Main_Activityは私の起動アクティビティです

public class Main_Activity extends Activity{
       private Controller simpleController;
       protected void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                 setContentView(R.layout.main);
                 simpleController = Controller.getInstance(this);
       }
}

これは私のControllerシングルトンです。その中で、今から10秒のアラームを設定していMyMainLocalRecieverます。そのアラームを受け取り、通知を使用して通知します。

public class Controller {
       private MediaPlayer mp;
       public Context context;
       private static Controller instance;

       public static Controller getInstance(Context context) {
              if (instance == null) {
                    instance = new Controller(context);
              }
              return instance;
       }

      private Controller(Context context) {
            Log.d("TAG", "Creating Controller object");
            mp = null;
            this.context = context;
            setAlarm(10);
        }

     public void setAlarm(int position) {
        Intent intent = new Intent(context, MyMainLocalReciever.class);
        intent.putExtra("alarm_id", "" + position);
        PendingIntent sender = PendingIntent.getBroadcast(context,
                position, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        // Get the AlarmManager service
        AlarmManager am = (AlarmManager) context
                .getSystemService(Activity.ALARM_SERVICE);
        am.cancel(sender);
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
                + (position*1000), sender);
    }

}

これは通知する受信者MyMainLocalRecieverであり、と呼ばれるアクティビティを開始するインテントをバインドしていますNotificationDialog

public class MyMainLocalReciever extends BroadcastReceiver {
private NotificationManager notificationManager;
private int alarmId = 0;

@Override
public void onReceive(Context context, Intent intent) {
    if (notificationManager == null) {
        notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
    }
    Bundle bundle = intent.getExtras();

    String alarm_Id = bundle.getString("alarm_id");

        try {
        alarmId = Integer.parseInt(alarm_Id);
    } catch (Exception e) {
        Log.d("Exception", "exception in converting");
    }

    Controller myC = Controller.getInstance(context);
    if ((myC.getMp() != null)) {
        myC.getMp().stop();
        myC.setMp(null);
    }
    if (myC.getMp() == null) {

            myC.setMp(MediaPlayer.create(context , R.id.mpFile));
            myC.getMp().start();
    }

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
            .setTicker("Its Ticker")
            .setSmallIcon(R.drawable.ic_launcher)
            .setContentTitle("Its Title")
            .setContentText("Its Context")
            .setAutoCancel(true)
            .setContentIntent(
                    PendingIntent.getActivity(context, 0, new Intent(context,
                            NotificationDialog.class)
                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                    | Intent.FLAG_ACTIVITY_CLEAR_TASK), 0));

    notificationManager.notify("interstitial_tag", alarmId,
            builder.getNotification());

}

}

今まで(前にNotificationDialog)コードは完全に機能しており、クラスMediaPlayer内にあるオブジェクトも正常に機能していますが、ここでシングルトンにアクセスすると、コントローラーの新しいオブジェクトが作成されます。それを行うべきではなく、シングルトンであるオブジェクトを保持する必要があります.ControllerControllerNotificationDialogController

public class NotificationDialog extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.notification_dialog);

}

public void onViewContent(View v) { //this method is invoked when I click on a button binded in xml file

    Controller myC = Controller.getInstance(getApplicationContext());

    if (myC.getMp() != null) {
        myC.getMp().stop();
        myC.setMp(null);
    }
    finish();
}

}

これに関して親切に私を助けてください、私はあなたの助けに感謝します. よろしく

編集: これが私のマニフェストです

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".Main_Activity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="test.SettingsActivity"
        android:label="@string/app_name" />
    <activity
        android:name="test.NotificationDialog"
        android:label="@string/app_name" />
    <service android:name="test.MyService" >
    </service>

    <receiver
        android:name="test.MyMainLocalReciever"
        android:process=":remote" />
</application>
4

3 に答える 3

6

バックグラウンドでアイドル状態のときに、プロセスが Android によって強制終了されています。アクティブなコンポーネント (アクティビティ、サービスなど) がない場合、またはメモリが必要な場合 (アクティブなコンポーネントがある場合でも)、Android はプロセスを強制終了します。

ユーザーが通知を使用すると、Android は新しいプロセスを作成します。そのため、Singleton はなくなり、再作成する必要があります。

編集:

マニフェストを投稿した後、すぐに問題がわかりました。これです:

<receiver
    android:name="test.MyMainLocalReciever"
    android:process=":remote" />

あなたのプロセスは殺されていません。BroadcastReceiver は別の別のプロセスで実行されています。そのプロセスでは、シングルトンはまだセットアップされていません。

マニフェストのタグから削除android:process=":remote"します。<receiver>

于 2012-07-12T13:26:21.957 に答える
1

Initialization-on-demand holder idiomについてお読みください。Java プログラミング言語での正しいシングルトンに関する非常に明確で単純な記事です。

于 2012-07-12T12:59:55.327 に答える
0

シングルトンは多くのアクティビティで使用される静的オブジェクトになるため、コンテキストをコンストラクターに渡す必要はありません。それを必要とするメソッドに渡すことは、より良いオプションです。

public class Controller {

        private static volatile Controller instance = null;

        private Controller () {   }

        public static Controller getInstance() {
                if (instance == null) {
                        synchronized (Controller .class)
                                if (instance == null) {
                                        instance = new Controller();
                                }
                }
                return instance;
        }

        public void setAlarm(Context context, int position) {
             // do stuff
        }
}
于 2012-07-12T13:04:14.277 に答える