Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/209.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Singleton对象正在重新创建_Java_Android_Singleton - Fatal编程技术网

Java Singleton对象正在重新创建

Java Singleton对象正在重新创建,java,android,singleton,Java,Android,Singleton,我面临一个问题,我创建了一个类Controller它是单例的,但当我在同一应用程序的不同活动中访问时,它的对象正在重新创建 主要活动是我的发布活动 public class Main_Activity extends Activity{ private Controller simpleController; protected void onCreate(Bundle savedInstanceState) { super.onCr

我面临一个问题,我创建了一个类
Controller
它是单例的,但当我在同一应用程序的不同活动中访问时,它的对象正在重新创建

主要活动是我的发布活动

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);
       }
}
这是我的
控制器
它是单例的,我在其中设置10秒后的报警,我的
MyMainLocalReceiver
接收该报警并使用通知进行通知

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

}
这是我的接收者
mymainlocalreceiver
it notify,我正在绑定一个意图,该意图启动一个名为
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
之前)code工作正常
MediaPlayer
对象在
Controller
类中也工作正常,但是当我在
NotificationDialog
中访问我的singleton
控制器时,它正在创建控制器的新对象,它不应该这样做,它应该保留
控制器
对象,它是单例的

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>

请阅读有关该项目的信息。这是一篇关于Java编程语言中正确的单例的非常清晰和简单的文章。

由于单例是许多活动使用的静态对象,您不必将上下文传递给构造函数。将它传递给需要它的方法是一个更好的选择

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

当进程在后台空闲时,它将被Android杀死。如果没有活动组件(活动、服务等),或者当进程需要内存时(即使您有活动组件),Android也会关闭您的进程

当用户使用您的通知时,Android会为您创建一个新流程。这就是为什么单身汉已经消失,需要重新创建

编辑:

在你发布清单后,我立即发现了问题所在。就是这样:

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

你的进程不会被破坏。您的BroadcastReceiver正在另一个单独的进程中运行。在这个过程中,单身汉还没有建立起来


从清单中的
标记中删除
android:process=“:remote”

我不认为您应该将活动实例附加到像该控制器这样的长寿命对象。活动旨在进入和退出存在。相反,只使用ApplicationContext,它至少在应用程序的生命周期内都会存在。实际上,我需要更新在
Controller
类中处理的UI
Main\u Activity
,这就是为什么我需要从主\u Activity:
Controller.getInstance()在
Controller
的构造函数中传递上下文引用.updateUI(本)我正在实现
MVC
,因此模型通知
控制器
我已更新,这就是我需要传递上下文的原因。我知道,但我必须将数据库类和视图分开,我不能在一个类中完成所有操作。谢谢先生的解释,但我现在应该做什么?这取决于;-)你的单身生活中有什么需要保存的?您可以将文件中的任何内容保存到共享首选项中,或者将其放入附加到通知意图的额外文件中。我只需要保留
Controller
类中的
MediaPlayer
对象的地址,我该怎么做?您不能延迟MediaPlayer对象的创建,直到需要使用它吗?我在你的控制器类中没有看到创建MediaPlayer的任何代码。当然,
android:process
属性告诉系统在特定进程中运行此组件。如果未指定此属性,则默认值为包的名称。因此,所有未指定此属性的组件都在一个以包的名称命名的进程中运行。当您在
标记中指定
android:process=“:remote”
时,您告诉android在另一个名为
:remote
的进程中运行您的BroadcastReceiver。如果要将应用程序拆分为多个进程(即:一个进程中的服务,另一个进程中的活动),此模式非常有用,但与问题无关。他对单身汉的管理还不错。问题是Android正在扼杀和重建他的进程。使用单例的延迟初始化无助于解决此问题。