Android中嵌套片段之间的通信 [英] Communication between nested fragments in Android

查看:89
本文介绍了Android中嵌套片段之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近学习了如何在Android中制作嵌套片段.不过,我不知道应该如何进行交流.

I recently learned how to make nested fragments in Android. I don't know how communication is supposed to happen, though.

通过阅读片段通信文档,我知道

所有片段到片段的通信都是通过关联的 活动.两个片段永远不要直接通信.

All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.

这对于活动中的同级片段很有意义,但对父子片段通信而言却没有多大意义.我是否需要一直进行到活动之前,以便孩子片段与父片段进行对话?如果答案是简单的是",那么我可以做到.如果为否",那么代码设计将是什么样?

This makes sense for sibling fragments within an activity, but it doesn't make as much sense for parent-child fragment communication. Do I need to go all the way up to the Activity just for the Child Fragment to talk to the Parent Fragment? If the answer is a simple "yes" then I can do that. If it is a "no", then what would the code design look like?

我在嵌套片段文档中看到,使用 getParentFragment() 以获得对父级的引用分段.那么这是否意味着孩子应该直接与父母沟通?这似乎与正常片段与父活动进行通信所鼓励的相反.

I see in the Nested Fragment documentation that one can use getParentFragment() to get a reference to the parent fragment. So does that mean that the child should directly communicate with the parent? That seems opposite from what is encouraged with a normal fragment communicating with the parent activity.

推荐答案

按照评论中Rahul Sharma的建议,我使用接口回调从子片段到父片段以及活动进行通信.我还将此答案提交了代码审查" .我认为(在撰写本文时)那里没有答案,这表明该设计模式没有大的问题.在我看来,这与官方片段通信文档.

Following Rahul Sharma's advice in the comments, I used interface callbacks to communicate up from the Child Fragment to the Parent Fragment and to the Activity. I also submitted this answer to Code Review. I am taking the non-answer there (at the time of this writing) to be a sign that there are no major problems with this design pattern. It seems to me to be consistent with the general guidance given in the official fragment communication docs.

以下示例项目扩展了问题中给出的示例.它具有用于启动从片段到活动以及从子片段到父片段的向上通信的按钮.

The following example project expands the example given in the question. It has buttons that initiate upward communication from the fragments to the activity and from the Child Fragment to the Parent Fragment.

我这样设置项目布局:

Activity从两个片段中实现侦听器,以便它可以从中获取消息.

The Activity implements the listeners from both fragments so that it can get messages from them.

可选的TODO:如果Activity要启动与片段的通信,它可以直接获取它们的引用,然后调用其公共方法之一.

Optional TODO: If the Activity wanted to initiate communication with the fragments, it could just get a direct reference to them and then call one of their public methods.

import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnChildFragmentToActivityInteractionListener {

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

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.parent_fragment_container, new ParentFragment());
        ft.commit();
    }

    @Override
    public void messageFromParentFragmentToActivity(String myString) {
        Log.i("TAG", myString);
    }

    @Override
    public void messageFromChildFragmentToActivity(String myString) {
        Log.i("TAG", myString);
    }
}

父片段

父片段从子片段实现侦听器,以便它可以接收来自其的消息.

Parent Fragment

The Parent Fragment implements the listener from the Child Fragment so that it can receive messages from it.

可选的TODO:如果父片段"想要启动与子片段"的通信,则它可以直接获得对其的引用,然后调用其公共方法之一.

Optional TODO: If the Parent Fragment wanted to initiate communication with the Child Fragment, it could just get a direct reference to it and then call one of its public methods.

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class ParentFragment extends Fragment implements View.OnClickListener, ChildFragment.OnChildFragmentInteractionListener {


    // **************** start interesting part ************************

    private OnFragmentInteractionListener mListener;


    @Override
    public void onClick(View v) {
        mListener.messageFromParentFragmentToActivity("I am the parent fragment.");
    }

    @Override
    public void messageFromChildToParent(String myString) {
        Log.i("TAG", myString);
    }

    public interface OnFragmentInteractionListener {
        void messageFromParentFragmentToActivity(String myString);
    }

    // **************** end interesting part ************************



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_parent, container, false);
        view.findViewById(R.id.parent_fragment_button).setOnClickListener(this);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Fragment childFragment = new ChildFragment();
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        transaction.replace(R.id.child_fragment_container, childFragment).commit();
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

}

儿童片段

Child Fragment为Activity和Parent Fragment定义了侦听器接口.如果子片段"仅需要与其中一个进行通信,则可以删除另一个接口.

Child Fragment

The Child Fragment defines listener interfaces for both the Activity and for the Parent Fragment. If the Child Fragment only needed to communicate with one of them, then the other interface could be removed.

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class ChildFragment extends Fragment implements View.OnClickListener {


    // **************** start interesting part ************************

    private OnChildFragmentToActivityInteractionListener mActivityListener;
    private OnChildFragmentInteractionListener mParentListener;

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.child_fragment_contact_activity_button:
                mActivityListener.messageFromChildFragmentToActivity("Hello, Activity. I am the child fragment.");
                break;
            case R.id.child_fragment_contact_parent_button:
                mParentListener.messageFromChildToParent("Hello, parent. I am your child.");
                break;
        }
    }

    public interface OnChildFragmentToActivityInteractionListener {
        void messageFromChildFragmentToActivity(String myString);
    }

    public interface OnChildFragmentInteractionListener {
        void messageFromChildToParent(String myString);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        // check if Activity implements listener
        if (context instanceof OnChildFragmentToActivityInteractionListener) {
            mActivityListener = (OnChildFragmentToActivityInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnChildFragmentToActivityInteractionListener");
        }

        // check if parent Fragment implements listener
        if (getParentFragment() instanceof OnChildFragmentInteractionListener) {
            mParentListener = (OnChildFragmentInteractionListener) getParentFragment();
        } else {
            throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener");
        }
    }

    // **************** end interesting part ************************



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        view.findViewById(R.id.child_fragment_contact_activity_button).setOnClickListener(this);
        view.findViewById(R.id.child_fragment_contact_parent_button).setOnClickListener(this);
        return view;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mActivityListener = null;
        mParentListener = null;
    }

}

这篇关于Android中嵌套片段之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆