简体   繁体   English

内部类初始化后如何访问自己的变量?

[英]How to access own variable upon initialization within inner class?

I have a "DialogHelper" class wherein a bunch of static methods are used in various contexts to make using Dialogs easier. 我有一个“ DialogHelper”类,其中在各种上下文中使用了一堆静态方法以使使用Dialogs更容易。 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: 但是,“ alert.show()”方法会引发错误:

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. 我已经遇到过几次这个问题,所以我最终决定问最好的解决方法是什么。

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: 我看到您的选择如下:

1. Wrap AlertDialog 1.包装AlertDialog

This is basically your work-around which uses an ArrayList , but you can create you own class for this purpose also. 这基本上是使用ArrayList ,但是您也可以为此创建自己的类。

2. Make AlertDialog a member 2.使AlertDialog成为成员

Declare alert be a private member of the class which contains the doSomething method, instead of declaring it in the method itself. 声明alert是包含doSomething方法的类的private成员,而不是在方法本身中声明它。

3. Replace your DialogHelper with a Builder 3.用构建器替换DialogHelper

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. 如果要在对话框中显示进度条,则可以在MyDialogBuilder上创建其他方法,这些方法将在回调中调用alert.dismiss() Hope this helps. 希望这可以帮助。

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

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