简体   繁体   English

Java中奇怪的初始化行为

[英]Strange behavior of initialization in Java

/**
 * Example Activity to demonstrate the lifecycle callback methods.
 */
public class ActivityA extends Activity {

    private String mActivityName;
    private TextView mStatusView;
    private TextView mStatusAllView;
    private StatusTracker mStatusTracker = StatusTracker.getInstance();
    private AlertDialog alertBox;
    private static int number = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);

        init();

        String output = getString(R.string.on_create) + number++;
        showAlertDialog(alertBox, output);
        mStatusTracker.setStatus(mActivityName, output);
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_start));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_restart));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_resume));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_pause));
        Utils.printStatus(mStatusView, mStatusAllView);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_stop));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mStatusTracker.setStatus(mActivityName, getString(R.string.on_destroy));
        mStatusTracker.clear();
    }

    public void startDialog(View v) {
        Intent intent = new Intent(ActivityA.this, DialogActivity.class);
        startActivity(intent);
    }

    public void startActivityB(View v) {
        Intent intent = new Intent(ActivityA.this, ActivityB.class);
        startActivity(intent);
    }

    public void startActivityC(View v) {
        Intent intent = new Intent(ActivityA.this, ActivityC.class);
        startActivity(intent);
    }

    public void finishActivityA(View v) {
        ActivityA.this.finish();
    }

    private void showAlertDialog(AlertDialog ad, String msg) {
        ad.setTitle("Logging Msg");
        ad.setMessage(msg);
        ad.show();
    }

    private void init() {
        System.out.println("Value = before &&&&&&&&& " + alertBox);
        if (alertBox == null) { // Why always null?
            alertBox = new AlertDialog.Builder(this).create();
            mActivityName = getString(R.string.activity_a);
            mStatusView = (TextView) findViewById(R.id.status_view_a);
            mStatusAllView = (TextView) findViewById(R.id.status_view_all_a);
            Log.e("ActivityA", "Init done **************************************");
            Log.e("ActivityA", "Init done **************************************");
            System.out.println("Value = after &&&&&&&&&&& " + alertBox);
        }
    }
}

Only the very first time the init is called, I set alertBox and I thought the if block should not be executed any other time. 只有在第一次调用init时,我才设置了AlertBox,我认为if块不应再执行。 But I am wrong, it runs every time init is being called. 但是我错了,它在每次调用init时都会运行。 Why? 为什么?

I came from Javascript, if I translate the above code into JS (similar), the if block is only evaluated once. 我来自Javascript,如果将上面的代码翻译成JS(类似),则if块仅计算一次。

alertBox is a member variable of a the class, ie each instance of the class has its own copy. alertBoxalertBox的成员变量,即该类的每个实例都有其自己的副本。 So if you have multiple instances of ActivityA each has its own alertBox all set to null initially. 因此,如果您有多个ActivityA实例,则每个实例都有其自己的alertBox ,最初alertBox都设置为null

If you want to share alertBox you need to declare it as static : 如果要共享alertBox ,则需要将其声明为static

private static AlertDialog alertBox;

Although, this might result in (additional) problems in a multi-threaded application, so use with care! 虽然,这可能会导致多线程应用程序出现(其他)问题,所以请谨慎使用!

You should check how your application follows the android activity lifecycle. 您应该检查您的应用程序如何遵循android活动生命周期。 The onCreate method gets called every time an Activity is created again (even if it existed before). 每次重新创建一个Activity时,都会调用onCreate方法(即使之前存在)。 Check if your onDestroy() method gets called. 检查您的onDestroy()方法是否被调用。 If the answer is yes, you now know how android handles its Activitys. 如果答案是肯定的,那么您现在知道android如何处理其Activity。 See http://developer.android.com/training/basics/activity-lifecycle/starting.html for an in detail explanation. 有关详细说明,请参见http://developer.android.com/training/basics/activity-lifecycle/starting.html

However if the answer is no, there is something wrong on your activity handling. 但是,如果答案是否定的,则您的活动处理有问题。 Maybe you recreate the same activity every time the user pushes a button etc. Maybe you finish() the activity somewhere. 也许您每次用户按下按钮等都重新创建相同的活动。也许您在某处finish()了活动。 But this is just wild guessing. 但这只是疯狂的猜测。

alertBox is declared as an instance variable. alertBox被声明为实例变量。

Maybe you should make alertBox a static variable if you only want to set it once for the class and not for every object instance. 如果只想为该类而不是为每个对象实例设置一次,则可能应将alertBox static变量。

Probably, the activity is destroyed and recreated, so the new object has alertBox as null. 该活动可能已销毁并重新创建,因此新对象的alertBox为null。

You should not change it to an static variable, because alertBox holds a reference to the activity where it was created (I'm not sure if it would even work correctly in other instances of the activity), so if you saved it in a static variable, it would prevent the original activity from being collected by the GC (garbage collector). 应该将其更改为静态变量,因为alertBox保持对创建它(我不知道它是否会甚至在活动的其他情况下正常工作)活动的参考,因此,如果你在一个静态保存它变量,它将防止原始活动被GC(垃圾收集器)收集。

Creating a new one in each instance of the activity is the right way to go (the way you are doing it now is fine). 在每个活动实例中创建一个新实例是正确的方法(您现在进行的方法就可以了)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM