Reputation: 1094
I have a "DialogHelper" class wherein a bunch of static methods are used in various contexts to make using Dialogs easier. One such method is a "three choice dialog" where the user has three buttons to choose from to go forward:
public static AlertDialog createThreeChoiceDialog(final MyActivity activity, String title, String firstChoiceText,
String secondChoiceText, String thirdChoiceText, View.OnClickListener firstChoiceListener, View.OnClickListener secondChoiceListener,
View.OnClickListener thirdChoiceListener) {
final View dView = activity.getLayoutInflater().inflate(R.layout.three_choice_dialog, null);
final TextView explanatoryTV = (TextView) dView.findViewById(R.id.explanatoryTV);
final TextView firstChoiceTV = (TextView) dView.findViewById(R.id.firstChoiceTV);
final TextView secondChoiceTV = (TextView) dView.findViewById(R.id.secondChoiceTV);
final TextView thirdChoiceTV = (TextView) dView.findViewById(R.id.thirdChoiceTV);
explanatoryTV.setText(title);
firstChoiceTV.setText(firstChoiceText);
secondChoiceTV.setText(secondChoiceText);
thirdChoiceTV.setText(thirdChoiceText);
firstChoiceTV.setOnClickListener(firstChoiceListener);
secondChoiceTV.setOnClickListener(secondChoiceListener);
thirdChoiceTV.setOnClickListener(thirdChoiceListener);
AlertDialog = etc...
return alertDialog;
}
And I call it like this:
private void doSomething() {
final AlertDialog alert = DialogHelper.createThreeChoiceDialog(activity, "title", "choice1", "choice2", "choice3",
new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 1
alert.dismiss();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 2
alert.dismiss();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 3
alert.dismiss();
}
});
alert.show();
}
However, the "alert.show()" method rings up the error:
variable 'alert' might not have been initialized yet
My question is, what is the best way to handle this situation? I want to dismiss the dialog when the user selects a choice.
This is my current workaround:
private void doSomething() {
final ArrayList<AlertDialog> alerts = new ArrayList<>(); //<-- added ArrayList of AlertDialogs
final AlertDialog alert = DialogHelper.createThreeChoiceDialog(activity, "title", "choice1", "choice2", "choice3",
new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 1
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 2
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something 3
alerts.get(0).dismiss(); //<-- accessed via ArrayList
}
});
alerts.add(alert); //<-- add alert to ArrayList
alert.show();
}
It works, but there's no way that this can be a best practice. I've run into this problem a few times, so I finally decided to ask what the best way to handle it is.
Upvotes: 0
Views: 50
Reputation: 3980
You are basically trying to reference an instance of a class while declaring and creating that instance - this is not possible.
I see your options as the following:
This is basically your work-around which uses an ArrayList
, but you can create you own class for this purpose also.
Declare alert
be a private
member of the class which contains the doSomething
method, instead of declaring it in the method itself.
There are several advantages (and 1 disadvantage) to this approach.
The first advantage is that it will solve your problem. The second is because it's good coding practice: in general, having methods with take many parameters is considered dirty. In the case of them being constructor methods, Clean Code conventions recommend replacing them with builders.
The disadvantage of the implementation I am about to suggest is that the Dialog behaviour is that clicking an option will always dismiss the dialog.
public class MyDialogBuilder {
private AlertDialog alert;
public MyDialogBuilder withActivity(Activity activity){
final View dView = activity.getLayoutInflater().inflate(R.layout.three_choice_dialog, null);
alert = ...;
return this;
}
public MyDialogBuilder withFirstChoice(String choiceText, final ChoiceAction action){
final TextView firstChoiceTV = (TextView) alert.findViewById(R.id.firstChoiceTV);
firstChoiceTV.setText(choiceText);
firstChoiceTV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
action.perform();
alert.dismiss();
}
});
return this;
}
// Similar implementations for the other methods here...
public AlertDialog create() {
return alert;
}
interface ChoiceAction {
void perform();
}
}
Your calling code would be like
MyDialogBuilder builder = new MyDialogBuilder();
AlertDialog alert = builder.withActivity(activity)
.withTitle("Dialog title")
.withFirstChoice("choice 1", new MyDialogBuilder.ChoiceAction() {
@Override
public void perform() {
//do something 1
}
})
.withSecondChoice("choice 2", new MyDialogBuilder.ChoiceAction() {
@Override
public void perform() {
//do something 2
}
})
.withThirdChoice("choice 3", new MyDialogBuilder.ChoiceAction() {
@Override
public void perform() {
//do something 3
}
})
.create();
I would recommend the third approach, as I think in most cases you want to close the Dialog when the user selects an option. If you want to show some progress bar in the dialog, you can create additional methods on MyDialogBuilder
which would call alert.dismiss()
in a callback. Hope this helps.
Upvotes: 1