安卓开发-Fragment与DialogFragment及Activity之间的通信

内容纲要

Fragment与DialogFragment及Activity之间的通信

  1. 要完成Fragment中弹出DialogFragment对话框,并且在Fragment中响应对话框按钮的点击操作,需要Fragment和DialogFragmeng通信

  2. 要完成Fragment给Activity传递切换Fragment信号,需要Fragment和Activity通信

DialogFragment传递数据给宿主Fragment

例如:把对话框输入的账户名和密码由DialogFragment传递给宿主Fragment以便完成进一步的网络请求

Fragment中创建DialogFragment对象

声明变量

//声明对话框
private RegisterDialogFragment registerDialogFragment;
//请求码声明为全局静态变量,方便Fragment传递数据时调用
public static final int REQUEST_CODE = 100;

创建对话框

public void mClick(View view){
    switch (view.getId()){
        case R.id.btn_register:
            //点击注册弹出对话框
            registerDialogFragment = new RegisterDialogFragment();
            //设定宿主Fragment为当前的Fragment
            registerDialogFragment.setTargetFragment(this,REQUEST_CODE);
            registerDialogFragment.show(getFragmentManager(),"Register");
            break;
        default:
            break;
    }
}

设定按钮监听方法

private void initComponent(){
    //找到按钮并重设监听器方法
    btnLogin = fragmentView.findViewById(R.id.btn_login);
    btnRegister = fragmentView.findViewById(R.id.btn_register);
    btnLogin.setOnClickListener(this::mClick);
    btnRegister.setOnClickListener(this::mClick);
}

创建方法处理来自对话框的意图

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (resultCode){
        case RegisterDialogFragment.RESULT_CODE_SURE:
            //请求码为100时,注册用户并关闭对话框
            String userName = data.getStringExtra("username");
            String userPassword = data.getStringExtra("password");
            edt_username.setText(userName);
            edt_password.setText(userPassword);
            register_user = new User(userName,userPassword);
            registerUser(register_user);
            registerDialogFragment.dismiss();
            break;
        case RegisterDialogFragment.RESULT_CODE_BACK:
            //请求码为200时,取消注册,关闭对话框
            registerDialogFragment.dismiss();
            break;
        default:
            break;
    }
}

DialogFragment发送意图

定义结果码

//结果码,确认注册
public static final int RESULT_CODE_SURE = 100;
//结果码,取消注册
public static final int RESULT_CODE_BACK = 200;

发送意图

//重写控件的onClick方法
public void mClick(View view) {
    switch (view.getId()){
        case R.id.btnSure:
            //确认注册,传递输入信息和关闭对话框请求
            edt_register_username = fragmentView.findViewById(R.id.edt_register_username);
            edt_register_password = fragmentView.findViewById(R.id.edt_register_password);
            final String username = edt_register_username.getText().toString();
            final String password = edt_register_password.getText().toString();
            final User user = new User(username,password);

            //通过Intend传递意图给父Fragment
            //判断是否有父Fragment
            if (getTargetFragment() == null){
                Log.i("myInfo","btnSure clicked but targetFrgment is null");
                return;
            }
            Intent intent_sure = new Intent();
            intent_sure.putExtra("username",username);
            intent_sure.putExtra("password",password);
            //回调父Fragment的意图处理函数
            getTargetFragment().onActivityResult(LoginFragment.REQUEST_CODE, RESULT_CODE_SURE , intent_sure);
            break;
        case R.id.btnBack:
            //取消注册,传递关闭对话框请求
            if (getTargetFragment() == null){
                Log.i("myInfo","btnBack clicked but targetFrgment is null");
                return;
            }
            Intent intent_back = new Intent();
            //回调宿主Fragment的意图处理函数
            getTargetFragment().onActivityResult(LoginFragment.REQUEST_CODE, RESULT_CODE_BACK , intent_back);
            break;
        default:
            break;
    }
}

对话框按钮设定监听方法

private void initComponent(){
    //获取按钮对象,设定监听方法
    btnSure = fragmentView.findViewById(R.id.btnSure);
    btnBack = fragmentView.findViewById(R.id.btnBack);
    btnSure.setOnClickListener(this::mClick);
    btnBack.setOnClickListener(this::mClick);
}

宿主Fragment传递数据给DialogFragment

暂时没用到,用到后补充

用接口实现Fragment传递数据给Activity

BaseFragment定义接口

将带接口的Fragment定义为BaseFragment,方便继承使用

定义接口

/*
    * Fragment 和 Activity 通信时使用的接口
    */
public interface FragmentCallBack{
    public void sendValue(Object... param); //Bundle
    public void sendAction();
}

和相应的的Activity绑定

@Override
public void onAttach(@NonNull Context context) {
    try {
        mCallBack = (FragmentCallBack) context;
    }catch (ClassCastException e){
        //抛出相关异常
        throw new ClassCastException(context.toString() + "must implement FragmentCallBack");
    }
    super.onAttach(context);
}

HomeActivity实现接口

实现接口

public class HomeActivity extends AppCompatActivity implements LoginFragment.FragmentCallBack {}

实现接口方法

@Override
public void sendValue(Object... param) {

}
@Override
public void sendAction() {
    replaceFragment(2,userFragment);
    Log.i("myInfo","sendValue succeed true");
}

综合代码

BaseFragment.java

public abstract class BaseFragment extends Fragment {
    private final String TAG = "BaseFragment";
    public FragmentCallBack mCallBack;

    /*
     * Fragment 和 Activity 通信时使用的接口
     */
    public interface FragmentCallBack{
        public void sendValue(Object... param); //Bundle
        public void sendAction();
        public void sendString(String str);
    }

    @Override
    public void onAttach(@NonNull Context context) {
        try {
            mCallBack = (FragmentCallBack) context;
        }catch (ClassCastException e){
            //抛出相关异常
            throw new ClassCastException(context.toString() + "must implement FragmentCallBack");
        }
        super.onAttach(context);
    }
}

LoginFragment.java

//对话框接口
//implements RegisterDialogFragment.RegisterDialogFragmentOnListener
public class LoginFragment extends BaseFragment{
    private View fragmentView;
    private Context mContext;

    User register_user,login_user;
    private EditText edt_username,edt_password;
    private Button btnLogin,btnRegister;

    private RegisterDialogFragment registerDialogFragment;
    //定义与DialogFragment进行交互的请求码
    public static final int REQUEST_CODE = 100;

    private static final int ERROR = 0;
    private static final int LOGIN_SUCCESS = 1;
    private static final int LOGIN_FAILE = 2;
    private static final int REGISTER_SUCCESS = 3;
    private static final int REGISTER_FAILE = 4;

    public LoginFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        fragmentView = inflater.inflate(R.layout.fragment_login, container, false);
        return fragmentView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        //创建视图完成后,设置对应参数
        initComponent();
        super.onViewCreated(view, savedInstanceState);
    }
    private void initComponent(){
        edt_username = fragmentView.findViewById(R.id.edt_username);
        edt_password = fragmentView.findViewById(R.id.edt_password);
        //找到按钮并重设监听器方法
        btnLogin = fragmentView.findViewById(R.id.btn_login);
        btnRegister = fragmentView.findViewById(R.id.btn_register);
        btnLogin.setOnClickListener(this::mClick);
        btnRegister.setOnClickListener(this::mClick);
    }
    //主线程创建消息处理机制
    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(android.os.Message msg) {
            switch (msg.what){
                case LOGIN_SUCCESS:
                    //验证成功,返回确认登录状态
                    boolean login_state;
                    login_state = true;
                    Log.i("myInfo","before sendValue");
                    mCallBack.sendAction();
                    mCallBack.sendString(login_user.getName());
                    Log.i("myInfo","after sendValue");
                    break;
                case LOGIN_FAILE:
                    ToastUtil.showToast(mContext,"账号或密码错误");
                    break;
                case REGISTER_SUCCESS:
                    ToastUtil.showToast(mContext,"用户注册成功");
                    break;
                case REGISTER_FAILE:
                    ToastUtil.showToast(mContext,"用户注册失败,该用户名已经存在");
                    break;
                default:
                    break;
            }
        }
    };

    private void checkUser(final User user){
        new Thread(new Runnable() {
            @Override
            public void run() {
                DBService service = DBService.getDbService();
                if(service.queryUserData(user)){
                    //将允许登录的消息发给主线程
                    Message msg = new Message();
                    msg.what = LOGIN_SUCCESS;
                    handler.sendMessage(msg);
                }else{
                    Message msg = new Message();
                    msg.what = LOGIN_FAILE;
                    handler.sendMessage(msg);
                }
            }
        }).start();
    }
    private void registerUser(final User user){
        new Thread(new Runnable() {
            @Override
            public void run() {
                DBService service = DBService.getDbService();
                if(service.registerUserData(user)){
                    //将注册成功的消息发给主线程
                    Message msg = new Message();
                    msg.what = REGISTER_SUCCESS;
                    handler.sendMessage(msg);
                }else{
                    Message msg = new Message();
                    msg.what = REGISTER_FAILE;
                    handler.sendMessage(msg);
                }
            }
        }).start();
    }

    public void mClick(View view){
        switch (view.getId()){
            case R.id.btn_login:
                final String name = edt_username.getText().toString();
                final String password = edt_password.getText().toString();
                login_user = new User(name,password);
                checkUser(login_user);
                break;
            case R.id.btn_register:
                //点击注册弹出对话框
                registerDialogFragment = new RegisterDialogFragment();
                //设定宿主Fragment为当前的Fragment
                registerDialogFragment.setTargetFragment(this,REQUEST_CODE);
                registerDialogFragment.show(getFragmentManager(),"Register");
                break;
            default:
                break;
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (resultCode){
            case 100:
                String userName = data.getStringExtra("username");
                String userPassword = data.getStringExtra("password");
                edt_username.setText(userName);
                edt_password.setText(userPassword);
                register_user = new User(userName,userPassword);
                registerUser(register_user);
                registerDialogFragment.dismiss();
                Log.i("myInfo","case 100: register");
                break;
            case 200:
                registerDialogFragment.dismiss();
                Log.i("myInfo","case 200: register");
                break;
            default:
                break;
        }
    }

    @Override
    public void onAttach(Context context) {
        try {
            mCallBack = (FragmentCallBack) context;
        }catch (ClassCastException e){
            //抛出相关异常
            throw new ClassCastException(context.toString() + "must implement FragmentCallBack");
        }
        mContext = context;
        super.onAttach(context);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mContext = null;
    }
}

RegisterDialogFragment.java

public class RegisterDialogFragment extends DialogFragment {
    private Context mContext;
    private View fragmentView;

    //返回结果码
    //确认注册
    public static final int RESULT_CODE_SURE = 100;
    //取消注册
    public static final int RESULT_CODE_BACK = 200;

    EditText edt_register_username,edt_register_password;
    Button btnSure,btnBack;

    public RegisterDialogFragment() {

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //获取对话框对象并设置背景为透明
        //getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        //获取xml文件构建成的View
        fragmentView = inflater.inflate(R.layout.fragment_dialog_register,container,false);
        return fragmentView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        //创建视图完成后,设置对应参数
        initComponent();
        super.onViewCreated(view, savedInstanceState);
    }
    private void initComponent(){
        //获取按钮对象,设定监听方法
        btnSure = fragmentView.findViewById(R.id.btnSure);
        btnBack = fragmentView.findViewById(R.id.btnBack);
        btnSure.setOnClickListener(this::mClick);
        btnBack.setOnClickListener(this::mClick);
    }

    public void mClick(View view) {
        switch (view.getId()){
            case R.id.btnSure:
                //确认注册,传递输入信息和关闭对话框请求
                edt_register_username = fragmentView.findViewById(R.id.edt_register_username);
                edt_register_password = fragmentView.findViewById(R.id.edt_register_password);
                final String username = edt_register_username.getText().toString();
                final String password = edt_register_password.getText().toString();
                final User user = new User(username,password);

                //通过Intend传递意图给父Fragment
                //判断是否有父Fragment
                if (getTargetFragment() == null){
                    Log.i("myInfo","btnSure clicked but targetFrgment is null");
                    return;
                }
                Intent intent_sure = new Intent();
                intent_sure.putExtra("username",username);
                intent_sure.putExtra("password",password);
                //回调父Fragment函数
                getTargetFragment().onActivityResult(LoginFragment.REQUEST_CODE, RESULT_CODE_SURE , intent_sure);
                Log.i("myInfo","btnSure clicked");
                break;
            case R.id.btnBack:
                //取消注册,传递关闭对话框请求
                if (getTargetFragment() == null){
                    Log.i("myInfo","btnBack clicked but targetFrgment is null");
                    return;
                }
                Log.i("myInfo","btnBack clicked");
                Intent intent_back = new Intent();
                getTargetFragment().onActivityResult(LoginFragment.REQUEST_CODE, RESULT_CODE_BACK , intent_back);
                break;
            default:
                break;
        }
    }
    @Override
    public void onAttach(@NonNull Context context) {
        mContext = context;
        //mCallback = (RegisterDialogFragmentOnListener)getActivity();
        super.onAttach(context);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mContext = null;
    }
}

发表评论