Fragments之间的交互(实现参数传递)

Fragments之间的交互(实现参数传递)

日常开发中,通常Fragments之间可能需要交互,比如基于用户事件改变Fragment的内容。所有Fragment之间的交互需要通过他们关联的Activity,两个Fragment之间不应该直接交互。
采用接口回调的方式来实现Fragments之间的交互,大致分为四步:

1.定义一个接口

  • 为了让Fragment与Activity交互,可以在Fragment类中定义一个接口,并在Activity中实现。Fragment在它们的生命周期的onAttach()方法中获取接口的实现,然后调用接口的方法来与Activity交互。

定义接口的代码如下:

public class ListFragment extends Fragment implements AdapterView.OnItemClickListener {

    private ListView mListView;
    private ListAdapter mAdapter;
    private List<String> mData;

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

    public static ListFragment newInstance(String type) {
        Bundle args = new Bundle();
        args.putString("type", type);
        ListFragment fragment = new ListFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (mData == null) {
            mData = new ArrayList<>();
        }
        loadData();
    }

    private void loadData() {
        for (int i = 0; i < 10; i++) {
            mData.add("Item" + i);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);
        mListView = (ListView) rootView.findViewById(R.id.list_view);

        mAdapter = new ListAdapter(getActivity(), mData);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(this);
        return rootView;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mOnListItemSelectedListener = (OnListItemSelectedListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnListItemSelectedListener");
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mOnListItemSelectedListener.onListItemSelected(position);
    }

    private OnListItemSelectedListener mOnListItemSelectedListener;

    public interface OnListItemSelectedListener {
        void onListItemSelected(int position);
    }


    /* ================适配器相关===============*/
    public class ListAdapter extends BaseAdapter {

        private List<String> mData;
        private Context mContext;

        public ListAdapter(Context context, List<String> data) {
            this.mContext = context;
            this.mData = data;
        }

        @Override
        public int getCount() {
            return mData.size() == 0 ? 0 : mData.size();
        }

        @Override
        public Object getItem(int position) {
            return mData == null ? null : mData.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, parent, false);
                holder.mTextView = (TextView) convertView.findViewById(R.id.text_view);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            String text = mData.get(position);
            if (text != null && !"".equals(text)) {
                holder.mTextView.setText(text);
            }
            return convertView;
        }

        public class ViewHolder {
            TextView mTextView;
        }
    }

}
  • 现在Fragment就可以通过OnListItemSelectedListener 接口实例的mOnListItemSelectedListener中的onListItemSelected()方法与Activity传递消息。
  • 我这个例子实现的是在ListFragment中点击ListView的一个Item,把这个Item的position传递给DetailFragment,DetailFragment展示具体的信息,如新闻列表,点击Item之后进入新闻详情页。
  • 当我们点击Item时,ListFragment用回调接口来传递事件给父Activity。
 @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mOnListItemSelectedListener.onListItemSelected(position);
    }

2.实现接口

  • 为了接收回调事件,宿主Activity必须实现Fragment中定义的接口。
  • MainActivity实现了ListFragment中的接口,如下代码:
public class MainActivity extends AppCompatActivity 
        implements ListFragment.OnListItemSelectedListener {

    private static final String TAG = "MainActivity";

    private ListFragment mListFragment;

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

        mListFragment = ListFragment.newInstance("ListFragment");
        ActivityUtil.addFragmentToActivity(getSupportFragmentManager(),
                mListFragment, R.id.frame_container);
    }

    @Override
    public void onListItemSelected(int position) {
        Log.d(TAG, position + "");
        Bundle args = new Bundle();
        args.putInt("position",position);
        DetailFragment fragment = DetailFragment.newInstance("DetailFragment");
        fragment.setArguments(args);
        ActivityUtil.addFragmentToActivity(getSupportFragmentManager(), fragment, R.id.frame_container);
    }
}

3.传递消息给Fragment

  • 宿主MainActivity中还包含了另外一个Fragment(DetailFragment),DetailFragment用来展示回调方法中指定Item的内容。在这种情况下,MainActivity可以把回调方法中接收到的position传递给DetailFragment。
 @Override
    public void onListItemSelected(int position) {
        Log.d(TAG, position + "");
        Bundle args = new Bundle();
        args.putInt("position",position);
        DetailFragment fragment = DetailFragment.newInstance("DetailFragment");
        fragment.setArguments(args);
        ActivityUtil.addFragmentToActivity(getSupportFragmentManager(), fragment, R.id.frame_container);
    }

4.接收传递的参数

  • 在DetailFragment中接收ListFragment传递的position参数
public class DetailFragment extends Fragment {

    private TextView mTextView;
    private Bundle args;

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

    public static DetailFragment newInstance(String type) {
        Bundle args = new Bundle();
        args.putString("type", type);
        DetailFragment fragment = new DetailFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        args = getArguments();//获取传递的参数
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
        mTextView = (TextView) rootView.findViewById(R.id.text_view);
        mTextView.setText(args.get("position").toString());
        return rootView;
    }
}

这样就实现了两个Fragment之间的交互。其核心就是拥有同一个宿主Activity的Fragments利用接口回调的方式实现参数的传递。

博客地址:http://tonycheng93.github.io/
源码地址:https://github.com/tonycheng93/Fragment2Fragment

原文地址:https://www.cnblogs.com/tonycheng93/p/5944508.html