回调应用之activity与fragment


  大家是否 对回调有了一点的认识。

所谓回调,就是客户程序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都用到回调机制,可以访问远程服务器程序。


 下面的是:C语言中回调函数解释:
回调函数(Callback Function)是怎样一种函数呢?
函数是用来被调用的,我们调用函数的方法有两种:
l         直接调用:在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行。这里,A称为“主叫函数”(Caller),B称为“被叫函数”(Callee)。
l         间接调用:在函数A的函数体里并不出现函数B的函数名,而是使用指向函数B的函数指针p来使内存中属于函数B的代码片断得以执行——听起来很酷,是吧。
比起直接调用来,间接调用的确麻烦,那为什么还要使用间接调用呢?原因很简单——直接调用把函数名都写进函数体了,经过编译器那么一编译,板上钉钉,A注定调用的是B了,这样的程序只能按照程序员事先设计好的流程执行下去,太呆板了。此时,间接调用的巨大灵活性就显现出来了。想一想,如果p是函数A的一个参数(参数是变量,是变量就可以变吗!),那么程序的最终用户完全可以通过操作来改变p的指向——这样,A在通过p调用函数的时候就有机会调用到不同的函数,这样程序的实用性和扩展性就强多了。



相信大家对activity 都很熟悉  ,在此就不累赘了,下面讲一下Fragment

  给一张 Activity 与 Fragment 生命周期的对比图片让大家加强 对Fragment 生命周期的记忆

                                    https://img-blog.csdn.net/20140719225005356?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

       可以看到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();  
            }  
        }  
      
    }  



与FragmentOne极其类似,但是我们提供了setListener这样的方法,意味着Activity不仅需要实现该接口,还必须显示调用mFTwo.setfTwoBtnClickListener(this)。

最后看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>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值