最近研究了下activity和fragment之间进行通信,所以做一下总结。
布局很简单,上面部分是一个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 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 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) 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 mList=new ArrayList<>();
LeftAdapter(Context context){
mContet=context;
}
public void notifyDataSetChanged(ArrayList 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之间的通信,欢迎大家留言谈论!~~