最近研究了下activity和fragment之间进行通信,所以做一下总结。

先看下效果图

Android Fragment 向activity通信 fragment与activity通信_android

布局很简单,上面部分是一个textView,左半部分和右半部分各为一个frameLayout,这两个frameLayout都是用来填充fragment,分别是LeftFragment和RightFragment。LeftFragment的布局就是一个简单的listview,RightFragment布局是一个textView和一个button。整个通信的思路是,首先在activity中把数据传递给LeftFragment,LeftFragment把数据填充到自身的listview中,之后通过点击listview中的item把被点击的postion传递给activity,activity再把postion传递给RightFragment,最后通过点击RightFragment中的button再把postion传传回给activity中,activity把postion更新到textview中。

通过以上方式,就形成了activty与fragment的数次通信。先来看下activity的代码。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        change= (TextView) findViewById(R.id.change);

        ArrayList<String> list = new ArrayList<>();//形成数据
        for (int i = 0; i < 10; i++) {
            list.add(i + "");
        }

        Bundle bundle=new Bundle();
        bundle.putStringArrayList(LeftFragment.KEY_DATA_TO_LEFT,list);

        leftFragment=new LeftFragment();
        leftFragment.setArguments(bundle);//数据传递给leftfragment

        manager=getSupportFragmentManager();
        //把leftFragment填充到activity中
        manager.beginTransaction().replace(R.id.left_content, leftFragment).commit();
    }

观察以上代码,activty通过new一个bundle来存储数据,之后调用setArguments把数据传递给leftFragment。在leftFragment中只需要通过getArguments()获取传递进来的bundle,再通过对应的key提取出存储的数据就可以对listview进行数据填充。

需要说明的是fragment不建议用构造函数来传递参数,因为通过这种方式传值,在某些特殊情况下fragment被销毁时,通过构造函数传递进来的参数就会变为null,会丢失参数,但是通过setArguments和getArguments的方式进行传递参数就不会出现上述情况。

至此就完成了activty向fragment的数据传递。接下来需要完成的是leftFragment向activity中传递数据。如何实现呢?其实利用回调方法可以轻松实现fragment向activity中传递参数。

首先在leftFragment中定义一个接口。

public interface Callbacks{
        public void onCallback(int id);
    }

然后让activty实现这个接口。activty中代码如下。

@Override
    public void onCallback(int id) {
        rightFragment=new RightFragment();
        Bundle bundle=new Bundle();
        bundle.putInt(RightFragment.KEY_DATA_TO_RIGHT,id);
        rightFragment.setArguments(bundle);
        manager.beginTransaction().replace(R.id.right_content, rightFragment).commit();
    }

activty通过回调方法onCallback,获取传递过来的position信息,然后把这个参数再次通过setArguments和getArguments方式传递给RightFragment。

接着在leftFragment还需要进行如下操作。

private Callbacks callbacks;//声明一个Callbacks接口

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof Callbacks)
            //因为acitvity实现了Callbacks 接口,所以可以通过强转activity来实例化callbacks 
            callbacks = (Callbacks) activity;
        }
    }

    leftList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                callbacks.onCallback(position);
            }
        });

在listview的itemClick事件中,通过回调方法onCallback把被点击的position传递给activity。fragment向activity中传递参数也完成了。

最后实现RightFragment再向activity中传递参数,首先可以像上述方法一样通过回调,这里不用这个方法,我们利用handler实现。

首先在activity中定义一个静态的handler

public static Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            if(msg.what == 0){
                int index= (int) msg.obj;
                change.setText("点击了第"+index);
            }
        };
    };

然后为RightFragment中的button设置点击事件,在点击事件中通过MainActivity的handler传递参数。

action.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = new Message();
                msg.what = 0;
                msg.obj = index;
                MainActivity.handler.sendMessage(msg);
            }
        });

好了,这个通信流程都说清楚了,下面总结下:
1、activity向fragment中传递参数可以通过setArguments和getArguments的方式。
2、fragment向activity中传递参数可以通过自定义回调方法,也可以通过handler,当然更可以通过广播,但是还是推荐使用回调。

最后把两个fragment的代码贴一下。

leftfragment的代码如下

package com.afun.fragmentdemo.fragment;

import android.app.Activity;
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;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.afun.fragmentdemo.R;

import java.util.ArrayList;

public class LeftFragment extends Fragment{
    private ListView leftList;
    private ArrayList<String> dataList;
    private Callbacks callbacks;

    public static final String KEY_DATA_TO_LEFT   ="KEY_DATA_TO_LEFT";

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof Callbacks){
            callbacks = (Callbacks) activity;
        }

    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.left_fragment, container, false);
        leftList= (ListView) view.findViewById(R.id.left_list);
        Bundle bundle=getArguments();
        if(bundle!=null){
            dataList= (ArrayList<String>) bundle.get(KEY_DATA_TO_LEFT);
        }
        LeftAdapter adapter=new LeftAdapter(getActivity());
        leftList.setAdapter(adapter);
        leftList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                callbacks.onCallback(position);
            }
        });
        adapter.notifyDataSetChanged(dataList);
        return view;
    }

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

    public interface Callbacks{
        public void onCallback(int id);
    }

    static class LeftAdapter extends BaseAdapter{
        private Context mContet;
        private ArrayList<String> mList=new ArrayList<>();

        LeftAdapter(Context context){
            mContet=context;
        }

        public void notifyDataSetChanged(ArrayList<String> list) {
            mList=list;
            super.notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view=View.inflate(mContet,R.layout.item,null);
            TextView content= (TextView) view.findViewById(R.id.item_content);
            content.setText("这是第"+mList.get(position)+"个item");
            content.setTextColor(mContet.getResources().getColor(R.color.white));
            return view;
        }
    }
}

rightfragment代码如下

package com.afun.fragmentdemo.fragment;

import android.os.Bundle;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.afun.fragmentdemo.MainActivity;
import com.afun.fragmentdemo.R;


public class RightFragment extends Fragment {

    public static final String KEY_DATA_TO_RIGHT   ="KEY_DATA_TO_LEFT";
    private int index;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.right_fragment, container, false);
        TextView content= (TextView) view.findViewById(R.id.item_content);
        Button action= (Button) view.findViewById(R.id.action);
        Bundle bundle=getArguments();
        if(bundle!=null){
            index=bundle.getInt(KEY_DATA_TO_RIGHT);
        }
        content.setText("你点击了第"+index+"个item");
        action.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = new Message();
                msg.what = 0;
                msg.obj = index;
                MainActivity.handler.sendMessage(msg);
            }
        });
        return  view;
    }
}

ok,如果有更好的方式进行fragment与activity之间的通信,欢迎大家留言谈论!~~