Android中activity与fragment通信
一、activity之间传值
- 通过intent传递数据
- 通过Application
- 使用单例
- 静态成员变量
- 持久化(sqlite、share preference、file等)
1、通过intent传递数据
- 直接传递,intent.putExtra(key, value)
- 通过bundle,intent.putExtras(bundle);
注意:
①这两种都要求传递的对象必须可序列化(Parcelable、Serializable),特别注意对象中对象也要序列化
②Parcelable实现相对复杂
③关于Parcelable和Serializable,官方说法:
Serializable: it's error prone and horribly slow. So in general: stay away from Serializable if possible.
也就是说和Parcelable相比,Seriaizable容易出错并且速度相当慢。
④通过intent传递数据是有大小限制滴,超过限制,要么抛异常,要么新的Activity启动失败,所以还是很严重的啊。
2、Application
将数据保存在全局Application中,随整个应用的存在而存在,这样很多地方都能访问。
但是需要注意的是:
当由于某些原因(比如系统内存不足),我们的app会被系统强制杀死,此时再次点击进入应用时,系统会直接进入被杀死前的那个界面,制造一种从来没有被杀死的假象。那么问题来了,系统强制停止了应用,进程死了,那么再次启动时Application自然新的,那里边的数据自然木有啦,如果直接使用很可能报空指针或者其他错误。
因此还是要考虑好这种情况的:
①使用时一定要做好非空判断
②如果数据为空,可以考虑逻辑上让应用直接返回到最初的activity,比如用 FLAG_ACTIVITY_CLEAR_TASK 或者 BroadcastReceiver 杀掉其他的activity。
3、使用单例
比如一种常见的写法:
public class DataHolder {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
private static final DataHolder holder = new DataHolder();
public static DataHolder getInstance() {return holder;}
}
这样在启动activity之前:
DataHolder.getInstance().setData(data);
新的activity中获取数据:
String data = DataHolder.getInstance().getData();
4、静态Static
public static final String SEX = "sex";
5、持久化数据
sqlite、share preference、file
二、fragment之间传值
三、activity与fragment之间传值
1、activity向fragment传值:采用bundle方式
activity布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/rainbow_yellow"
android:orientation="vertical"
tools:context="com.anwanfei.anfly.summary.activity.FragmentTestActivity">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="我是Activity"
android:textColor="@color/colorPrimary"
android:textSize="20dp" />
<FrameLayout
android:layout_margin="20dp"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/button" />
</LinearLayout>
fragment布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/rainbow_red"
android:orientation="vertical">
<TextView
android:id="@+id/fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="我是fragment"
android:textColor="@color/colorPrimary"
android:textSize="30dp" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@color/white"
android:text="等待Activity发送消息"
android:textSize="20dp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:text="点击接收Activity消息"
android:textSize="20dp" />
</LinearLayout>
activity中:
public class FragmentTestActivity extends BaseActivity {
@BindView(R.id.text)
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void initView() {
//获取fragmentmanager
FragmentManager supportFragmentManager = getSupportFragmentManager();
//获取fragmentTranscation
FragmentTransaction ft = supportFragmentManager.beginTransaction();
//创建需要添加的fragment
TestFragment testFragment = new TestFragment();
//创建bundle对象
Bundle bundle = new Bundle();
//往bundle中添加数据
bundle.putString("message","我来自FragmentTestActivity");
//把数据设置到fragment中
testFragment.setArguments(bundle);
//动态添加fragment
ft.add(R.id.fragment_container,testFragment);
ft.commit();
}
@Override
public int getLayoutId() {
return R.layout.activity_fragment_test;
}
}
fragment中:
public class TestFragment extends BaseFragment {
@BindView(R.id.fragment)
TextView fragment;
@BindView(R.id.text)
TextView text;
@BindView(R.id.button)
Button button;
Unbinder unbinder;
private String message;
@Override
protected View initView() {
View view = View.inflate(getActivity(), R.layout.fragment_test, null);
return view;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO: inflate a fragment view
View rootView = super.onCreateView(inflater, container, savedInstanceState);
unbinder = ButterKnife.bind(this, rootView);
return rootView;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
protected void initData() {
super.initData();
//通过argument获取activity传过来的全部值
Bundle arguments = this.getArguments();
//获取某一值
message = arguments.getString("message");
}
@OnClick(R.id.button)
public void onViewClicked() {
text.setText(message);
}
2、fragment向activity传–接口回调方式
- 接口回调:把实现了某一接口的类所创建的对象的引用 赋给 该接口声明的变量,通过该接口变量 调用 该实现类对象的实现的接口方法。
接口声明的变量 :Com com;
实现了Com接口的类(Com1)所创建的对象的引用 赋给 该接口声明的变量:Com com = new Com1;
通过该接口变量(com)调用 该实现类对象(Com1)的实现的接口方法(carson()) com.carson();
activtiy布局:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/text"
android:layout_centerInParent="true"
android:text="点击接收Fragment消息"
android:textSize="10dp" />
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="500dp"
android:layout_below="@+id/button" />
</LinearLayout>
fragment布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:gravity="center"
android:text="我是fragment"
android:textSize="30dp" />
</LinearLayout>
设置回调接口ICallback,用于activity与fragment之间通信:
public interface ICallback {
void getMessageFromFragment(String string);
}
设置fragment类
public class MyFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
return view;
}
//设置接口回调方法
public void sendMessage(ICallback iCallback) {
iCallback.getMessageFromFragment("我是来自fragment的消息");
}
}
设置Activity类文件
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textview = (TextView) findViewById(R.id.textview);
Button button = (Button) findViewById(R.id.button);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
final MyFragment myFragment = new MyFragment();
fragmentTransaction.add(R.id.fragment_container, myFragment);
fragmentTransaction.commit();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//通过接口回调的方法获取fragment的消息
myFragment.sendMessage(new ICallback() {
@Override
public void getMessageFromFragment(String string) {
textview.setText(string);
}
});
}
});
}
}