0

Consider this DialogFragment:

public class RollTriggerDialog extends DialogFragment{

    private ProgressDialog _dialog;
    int _progress;
    public Handler _progressHandler;

    public RollTriggerDialog() {
        // empty
    }

    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {
        _dialog = new ProgressDialog(getActivity());

        this.setStyle(STYLE_NO_TITLE, getTheme());
        _dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        _dialog.setProgress(0);

        _progressHandler = new Handler() {
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                if (_progress >= 100) {
                    _dialog.dismiss();
                } else {
                    _progress++;
                    _dialog.incrementProgressBy(1);
                    _progressHandler.sendEmptyMessageDelayed(0,100);
                }

            }
        };
        //_progressHandler.sendEmptyMessage(0); <- This uncommented would start the progress
        return _dialog;
    }
}

It is just a horizontal progressbar with a handler, once the handler receives one message the progressbar goes from 0 to 100.

I am always getting a Null Pointer Exception if I want to trigger that sendEmptyMessage by myself from an activity:

public class MainActivity extends FragmentActivity {

    private RollTriggerDialog mRollTriggerDialog;

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

        FragmentManager fm = getSupportFragmentManager();
        mRollTriggerDialog = new RollTriggerDialog();
        mRollTriggerDialog.show(fm, "addDiceDialog_tag");
        ((RollTriggerDialog)fm.findFragmentByTag("addDiceDialog_tag"))._progressHandler.sendEmptyMessage(0); // <--- NPE HERE!
    }
}

If the line of sendEmptyMessage is uncommented in the dialogFragment and the line with NPE in the main activity is commented; the app runs. What is wrong with that invocation?

Note that this is the whole code, excepting manifest and layout files.

quinestor
  • 1,432
  • 4
  • 19
  • 40

1 Answers1

1

The NullPointerException appears because the findFragmentByTag returns null. The solution is to call fm.executePendingTransactions() before you use the findFragmentByTag method to execute that fragment transaction right away(see this question for more details).

Also, the Handler reference will be null at that moment so you'll want to initialize it in one of the fragment's lifecycle methods, for example, onCreate:

public static Handler _progressHandler; // should be made static

//...
@Override
public void onCreate(Bundle savedInstanceState) {       
    super.onCreate(savedInstanceState);
    _progressHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            if (_progress >= 100) {
                _dialog.dismiss();
            } else {
                _progress++;
                _dialog.incrementProgressBy(1);
                _progressHandler.sendEmptyMessageDelayed(0, 100);
            }

        }
    };
}
Community
  • 1
  • 1
user
  • 86,916
  • 18
  • 197
  • 190
  • Thanks Luksprog, I'll check tonight how this work. Now regarding the handler: you mean to initialize it in OnCreate instead of onCreateDialog like i did in my question? As a side note I think that your declaration will give a compiler error since the handler is using non-static refferences like _dialog – quinestor Oct 09 '12 at 13:29
  • 1
    @quinestor You have to initialize the handler reference earlier because the `onCreateDialog` will be called **after** the `onCreate` method of the `Activity`(so you'll have a null handler reference until then). If you would have initialized the handler with an instance of the `Handler` class as a field, yes you would need to declare the rest of the fields as `static`. But as you initialize the handler reference in a non static method you are pretty much guaranteed to have those field initialized correctly by the time you get in that method. I'm not quite sure so you'll need to test it. – user Oct 09 '12 at 14:07
  • Yes Luksprog, that was it. Both move initialization to onCreate and executePndingTransactions(), which I see I have to read more about. +1 to all :) About the static handler , well that is another question and I think I'll manage – quinestor Oct 09 '12 at 19:51