大家是否 对回调有了一点的认识。
所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数R告诉S自己将要使用B函数,这个过程称为回调函数的注册,R称为注册函数。Web Service以及Java的RMI都用到回调机制,可以访问远程服务器程序。
相信大家对activity 都很熟悉 ,在此就不累赘了,下面讲一下Fragment
给一张 Activity 与 Fragment 生命周期的对比图片让大家加强 对Fragment 生命周期的记忆
可以看到Fragment比Activity多了几个额外的生命周期回调方法:
1、onAttach(Activity); //当Fragment与Activity发生关联时调用。
2、onCreateView(LayoutInflater, ViewGroup,Bundle) ; //创建该Fragment的视图
3、onActivityCreated(Bundle) ; //当Activity的onCreate方法返回时调用
4、onDestoryView(); //与onCreateView想对应,当该Fragment的视图被移除时调用
5、onDetach(); //与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,
以下是FragmentTransaction的相关方法及说明:
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务
1、transaction.add() //往Activity中添加一个Fragment
2、transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,Fragment将会被销毁。
3、transaction.replace() //使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
4、transaction.hide() //隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
5、transaction.show() //显示之前隐藏的Fragment
6、detach() //会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
7、attach() //重建view视图,附加到UI上并显示。
8、transatcion.commit()//提交一个事务
注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。
Fragment与Activity通信
因为所有的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为:
a、如果你Activity中包含自己管理的Fragment的引用,可以通过引用直接访问所有的Fragment的public方法
b、如果Activity中未保存任何Fragment的引用,那么没关系,每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例,然后进行操作。
c、在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作。
注:如果在Fragment中需要Context,可以通过调用getActivity(),如果该Context需要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。
因为要考虑Fragment的重复使用,所以必须降低Fragment与Activity的耦合,而且Fragment更不应该直接操作别的Fragment,毕竟Fragment操作应该由它的管理者Activity来决定。
下面我通过两种方式的代码,分别重构,FragmentOne和FragmentTwo的点击事件,以及Activity对点击事件的响应:
首先看FragmentOne
<span style="font-size:14px;"> package com.fx678.finace;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
/**
* @author www.fx678.com
*/
public class FragmentOne extends Fragment implements OnClickListener{
private Button mBtn;
/**
* 设置按钮点击的回调
*/
public interface FOneBtnClickListener {
void onFOneBtnClick();
}
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_one, container, false);
mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);
mBtn.setOnClickListener(this);
return view;
}
/**
* 交给宿主Activity处理,如果它希望处理
*/
@Override
public void onClick(View v) {
if (getActivity() instanceof FOneBtnClickListener) {
((FOneBtnClickListener) getActivity()).onFOneBtnClick();
}
}
} </span>
可以看到现在的FragmentOne不和任何Activity耦合,任何Activity都可以使用;并且我们声明了一个接口,来回调其点击事件,想要管理其点击事件的Activity实现此接口就即可。可以看到我们在onClick中首先判断了当前绑定的Activity是否实现了该接口,如果实现了则调用。
再看FragmentTwo
package com.<span style="font-size:14px;">fx678.finace</span>;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
<span style="font-size:14px;">/**
* @author www.fx678.com
*/ </span>
public class FragmentTwo extends Fragment implements OnClickListener{
private Button mBtn ;
private FTwoBtnClickListener fTwoBtnClickListener ;
public interface FTwoBtnClickListener {
void onFTwoBtnClick();
}
//设置回调接口
public void setfTwoBtnClickListener(FTwoBtnClickListener fTwoBtnClickListener){
this.fTwoBtnClickListener = fTwoBtnClickListener;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_two, container, false);
mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);
mBtn.setOnClickListener(this);
return view ;
}
@Override
public void onClick(View v){
if(fTwoBtnClickListener != null){
fTwoBtnClickListener.onFTwoBtnClick();
}
}
}
最后看MainActivity :
<span style="font-size:14px;"> package com.fx678.finace;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Window;
import com.zhy.zhy_fragments.FragmentOne.FOneBtnClickListener;
import com.zhy.zhy_fragments.FragmentTwo.FTwoBtnClickListener;
/**
* @author www.fx678.com
*/
public class MainActivity extends Activity implements FOneBtnClickListener, FTwoBtnClickListener {
private FragmentOne mFOne;
private FragmentTwo mFTwo;
private FragmentThree mFThree;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mFOne = new FragmentOne();
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
tx.add(R.id.id_content, mFOne, "ONE");
tx.commit();
}
/**
* FragmentOne 按钮点击时的回调
*/
@Override
public void onFOneBtnClick(){
if (mFTwo == null){
mFTwo = new FragmentTwo();
mFTwo.setfTwoBtnClickListener(this);
}
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
tx.replace(R.id.id_content, mFTwo, "TWO");
tx.addToBackStack(null);
tx.commit();
}
/**
* FragmentTwo 按钮点击时的回调
*/
@Override
public void onFTwoBtnClick(){
if (mFThree == null){
mFThree = new FragmentThree();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction tx = fm.beginTransaction();
tx.hide(mFTwo);
tx.add(R.id.id_content, mFThree, "THREE");
// tx.replace(R.id.id_content, fThree, "THREE");
tx.addToBackStack(null);
tx.commit();
}
} </span>