侦听器空对象引用

时间:2018-06-13 18:33:48

标签: android

我的onAttach()方法将上下文分配给侦听器,但是,我的侦听器以某种方式为null。我该如何正确解决这个问题?我希望你能为我提供一些指示代码吗?

选择屏幕类初始化对话框(在本例中为nameDialog):

public class ChooseScreen extends AppCompatActivity {
private Button vsFriend;
private Button vsAndroid;
private NameDialog.NameDialogListener listener;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_choose_screen);
    vsFriend = findViewById(R.id.vsF);
    vsAndroid = findViewById(R.id.vsA);

    vsFriend.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            openDialog();
        }
    });
}

public void openDialog() {
    NameDialog nameDialog = new NameDialog();
    nameDialog.show(getSupportFragmentManager(), "example");

}

}

带有getTexts接口的NameDialog类:

public class NameDialog extends AppCompatDialogFragment  {
private EditText firstPlayer;
private EditText secondPlayer;
private NameDialogListener listener;


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    LayoutInflater inflater = getActivity().getLayoutInflater();
    final View view = inflater.inflate(R.layout.layout_dialog, null);

    firstPlayer = view.findViewById(R.id.edit_player1);
    secondPlayer = view.findViewById(R.id.edit_player2);

    builder.setView(view)
            .setTitle("Names")
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            })
            .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String player1 = firstPlayer.getText().toString();
                    String player2 = secondPlayer.getText().toString();
                    listener.getTexts(player1, player2);
                    // Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
                    // startActivity(intent);
                }
            });

    return builder.create();
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
        try{
        listener = (NameDialogListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + "must implement");
        }
}

public interface NameDialogListener {
    void getTexts(String player1, String player2);
}
}

实现NameDialogListener并覆盖接口方法(getTexts)的游戏类:

public class Game extends AppCompatActivity implements 
NameDialog.NameDialogListener {
private TextView player1Name;
private TextView player2Name;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game);
    player1Name = findViewById(R.id.player1TextView);
    player2Name = findViewById(R.id.player2TextView);
}

@Override
public void getTexts(String player1, String player2) {
    player1Name.setText(player1);
    player2Name.setText(player2);
}

}

错误:如果我不使用try-catch块,则错误将为NullPointerException,因为listener为null!

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.user.tictactoe, PID: 30462
                  java.lang.ClassCastException: com.example.user.tictactoe.ChooseScreen@1a0a489must implement
                      at com.example.user.tictactoe.NameDialog.onAttach(NameDialog.java:62)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1372)
                      at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
                      at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
                      at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
                      at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
                      at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
                      at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6776)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)

2 个答案:

答案 0 :(得分:0)

当你附加你的片段时,你试图从你的ChoooseScreen Activity获得一个听众。 Activity未实现NameDialogListener,因此您获得了ClassCastException。在您的示例中,您会显示另一个Activity,确实会实现监听器的游戏,但是您添加Fragment的任何活动都需要实现监听器才能使用您的onAttach()代码。

简短回答:如果您想在Fragment中显示ChooseScreen,则您的代码需要ChooseScreen来实施NameDialogListener

答案 1 :(得分:0)

onAttach将获取您父项活动的上下文。从ChooseScreen活动打开对话框时,父级是ChooseScreen。接口回调将被赋予ChooseScreen本身。那么你需要做的是用player1Name和player2Name调用Intent。

无论如何,我会为你分享代码。

您的选择屏幕

public class ChooseScreen extends AppCompatActivity implements NameDialog.NameDialogListener {
    private Button vsFriend;
    private Button vsAndroid;
    private NameDialog.NameDialogListener listener;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_choose_screen);
        vsFriend = findViewById(R.id.vsF);
        vsAndroid = findViewById(R.id.vsA);

        vsFriend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openDialog();
            }
        });
    }

    public void openDialog() {
        NameDialog nameDialog = new NameDialog();
        nameDialog.show(getSupportFragmentManager(), "example");

    }

    @Override
    public void getTexts(String player1, String player2) {
        Intent intent = new Intent(this, Game.class);
        intent.putExtra("PLAYER_ONE", player1);
        intent.putExtra("PLAYER_TWO", player2);
        startActivity(intent);
    }
}

你的姓名对话

public class NameDialog extends AppCompatDialogFragment {
    private EditText firstPlayer;
    private EditText secondPlayer;
    private NameDialogListener listener;


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();
        final View view = inflater.inflate(R.layout.layout_dialog, null);

        firstPlayer = view.findViewById(R.id.edit_player1);
        secondPlayer = view.findViewById(R.id.edit_player2);

        builder.setView(view)
                .setTitle("Names")
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String player1 = firstPlayer.getText().toString();
                        String player2 = secondPlayer.getText().toString();
                        listener.getTexts(player1, player2);

                        //TODO you can simply use below code and comment listener.getTexts();
//                        Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
//                        intent.putExtra("PLAYER_ONE", player1);
//                        intent.putExtra("PLAYER_TWO", player2);
//                        startActivity(intent);
                    }
                });

        return builder.create();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            listener = (NameDialogListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + "must implement");
        }
    }

    public interface NameDialogListener {
        void getTexts(String player1, String player2);
    }
}

你的游戏

public class Game extends AppCompatActivity
       /* implements NameDialog.NameDialogListener*/ {
    private TextView player1Name;
    private TextView player2Name;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);
        player1Name = findViewById(R.id.player1TextView);
        player2Name = findViewById(R.id.player2TextView);

        player1Name.setText(
                getIntent().getStringExtra("PLAYER_ONE"));
        player2Name.setText(
                getIntent().getStringExtra("PLAYER_TWO"));
    }

//    @Override
//    public void getTexts(String player1, String player2) {
//    }

}

试试这个让我知道......