• android--fragment详解


         Fragment(碎片)是作为android3.0(api level 11)发布版本的一部分而引入的;Fragment允许将activity拆分成多个完全独立封装的可重用的组件,每个组件有它自己的生命周期和ui布局。

    Fragment包含了一系列和acitivity类相像的事件处理程序。当Fragment被创建,启动,恢复,暂停,停止和销毁时,这些事件处理程序就会被触发。Fragment还包含了一些额外的callback,用来标识,Fragment和它的父acitivity之间的绑定和解绑定关系,Fragment的view层次的创建(和销毁)情况,以及它的父activity的创建过程完成情况。如下图所示:

    程序清单中展示一个Fragment生命周期中可用的基本方法,在每个基本方法的注释中描述了对于每个状态变化的事件,你应该考虑要做的动作

    package com.example.todolist;
     
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
     
    public class MyFragment extends Fragment{
     
     
        //调用该方法时Fragment会被连接到它的父activity上
        @Override
        public void onAttach(Activity activity) {
            // TODO Auto-generated method stub
            super.onAttach(activity);
            //获取对父activity的引用
        }
     
        //调用该方法来进行fragment的初始创建
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            //初始化fragment
        }
     
        //一旦fragment已被创建,要创建它自己的用户界面时调用该方法
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            //创建,或者填充fragment的ui,并返回它
            //如果这个fragment没有ui,那么返回null
            return super.onCreateView(inflater, container, savedInstanceState);
        }
     
     
        //一旦父activity和fragment的ui已被创建,则调用该方法
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onActivityCreated(savedInstanceState);
            //完成fragment的初始化--尤其是那些父activity被初始化完成后或者fragment的view被完全填充后才能做的事情
        }
        //在可见生命周期的开始时被调用
        @Override
        public void onStart() {
            // TODO Auto-generated method stub
            super.onStart();
            //应用所有需要的ui变化,现在fragment是可见的
        }
         
        //在活动生命周期的开始时被调用
        @Override
        public void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
            //恢复所有暂停的fragment需要的ui更新,线程或进程,但在非活动状态它是暂停的
        }
        //在活动生命周期结束时调用
        @Override
        public void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            //当activity不是活动的前台activity时,需要暂停ui的更新,挂起线程或者暂停那些不需要更新的cpu的集中处理。
            //档调用这个方法后,进程可能被终止,所以要保持所有的编辑和状态改变信息
        }
         
        //在活动生命周期结束时,调用该方法保持ui的状态变化
        @Override
        public void onSaveInstanceState(Bundle outState) {
            // TODO Auto-generated method stub
            super.onSaveInstanceState(outState);
            //将ui的状态改变信息保存到outstate中
            //这个bundle会被传递到oncreate,oncreateview和onactivitycreate(如果它的父activity被终止并重新启动)方法中
        }
        //在可见生命周期结束时调用该方法
        @Override
        public void onStop() {
            // TODO Auto-generated method stub
            super.onStop();
            //当fragment不可见时,暂停其余的ui更新,挂起线程或者暂停不再需要的处理
        }
        //  当fragment的view被分离时,调用该方法
        @Override
        public void onDestroyView() {
            // TODO Auto-generated method stub
            //清除资源相关的view
            super.onDestroyView();
        }
         
        //在整个生命周期结束时调用该方法
        @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
            //清除所有的资源,包括结束线程和关闭数据库连接等
            super.onDestroy();
        }
        //当fragment从它的父activity上分离时,当用该方法
        @Override
        public void onDetach() {
            // TODO Auto-generated method stub
            super.onDetach();
        }
     
    }

    demo应用切图:

    参考:http://www.2cto.com/kf/201403/288477.html

    关于Fragment的使用,网上有很多关于它的文章。一般的使用过程和生命周期之类的,就不在这讲述了,下附的demo也会对这些方面有所展示。这里主要讲讲我在开发使用Fragment的过程中遇到的一些问题和使用时注意的要点。

    首先要说的是,Fragment中有一个getActivity()的方法。这个方法会返回当前Fragment所附加的Activity。当fragment生命周期结束并销毁时,getActivity()返回的会是null。所以在使用时要注意判断null或者捕获空指针异常。但因为每次都要这样捕获一下,有些人可能就会和我一样,在创建fragment的时候就在构造器里面传一个activity的引用进去。这样的做法看似可以解决问题,但是其实是带着天大的隐患!因为activity传递得太多了,而且是传递给了另一个具有完整生命周期、可以长期运行且是在另一个页面进行执行的对象!这导致了activity的回收会很大地依赖众多的fragment,一旦业务比较多的时候,根本就看不来这么多地方,到底是哪里导致了activity的引用没有释放!这就导致了activity无法被回收。(虽然在我的项目里,我对这个问题进行了补救和处理,但也还是不大干净)。所以在这些情景,还是应该更多地关注android本身自带的生命周期管理函数。其实getActivity返回null的问题也只是让你要多判断一次而已,这没什么,从使用效益和合理性来说,这都不是一个问题。因为如果fragment已经销毁(onDestroy),这个页面也就没有使用意义,getActivity()之后的代码也就没有再继续执行的意义了(除非是一些异线程的处理,要注意线程也会跟着回收),所以只要判断getActivity()为空,就可以不再执行下面的代码,这完全不影响业务的使用。

    但如果想要离开这个页面,但还保留这个页面,就要注意不要让它被回收了。只要不回收,一切都还在~~

    另外,还有一个问题,就是一些没有被回收的线程在执行时,如果fragment已经销毁,那么它上面的那些控件,包括getActivity()都将是个空值,这时候就要在线程里面增加处理。

    当然,正常来说,如果这个线程是在fragment里面申请的那些线程,没有被当前fragment以外的对象引用,当该fragment被销毁的时候,接着也会把这个线程销毁,就好像销毁它的控件一样。

    /** 
     * Copyright (c) 2010-2013 王子 
     */  
    package cc.ives.fragment;  
      
    import android.app.Activity;  
    import android.app.Fragment;  
    import android.content.Context;  
    import android.os.Bundle;  
    import android.util.Log;  
    import android.view.LayoutInflater;  
    import android.view.View;  
    import android.view.ViewGroup;  
    import android.widget.TextView;  
      
    /** 
     * @author Administrator 
     * 
     */  
    public class FragmentOne extends Fragment {  
        private static final String TAG = "FragmentOne";  
        private Context context;  
        private TextView f1_txv;  
        public FragmentOne(Context context){  
            this.context = context;  
        }  
          
      
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                Bundle savedInstanceState) {  
            View view = inflater.inflate(R.layout.fragmentone, null);  
            f1_txv = (TextView) view.findViewById(R.id.txv_f1);  
            Thread t1 = new Thread(new Runnable() {  
                  
                @Override  
                public void run() {  
                    try {  
                        Thread.sleep(5000); //阻塞5秒  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    ((Activity)context).runOnUiThread(new Runnable() {  
        //如果(Activity)context改成getActivity(),当fragment销毁时,将是空值  
        //需要判断或捕获空指针异常解决问题。               
                        @Override  
                        public void run() {  
    //                      try{  
                            f1_txv.setText("f1 updated");   //2.如果线程销毁不够快,而fragment已经被销毁,则有可能抛异常  
      
    //                      }catch(NullPointerException e){  
    //                          Log.e(TAG, "捕获到异常");  
    //                      }  
                        }  
                    });  
                }         
            });  
            t1.start();  
              
            return view;  
        }  
      
        @Override  
        public void onDestroy() {  
            Log.e(TAG, "onDestroy");  
            super.onDestroy();  
        }  
      
      
        @Override  
        public void onPause() {  
            Log.e(TAG, "onPause");  
            super.onPause();  
        }  
      
      
        @Override  
        public void onResume() {  
            Log.e(TAG, "onResume");  
            super.onResume();  
        }  
      
      
        @Override  
        public void onStop() {  
            Log.e(TAG, "onStop");  
            super.onStop();  
        }  
      
          
    }  

    详细代码在 http://download.csdn.net/detail/wzg_1987/5338545

    原文在:http://blog.csdn.net/wzg_1987/article/details/8836532

  • 相关阅读:
    防止sql注入的方法
    二叉树的LCA(最近公共祖先)算法
    二叉树的计算
    @RestController和@Controller注解的区别
    单调栈与单调队列
    java中删除list指定元素遇到的问题
    随机打乱数组
    Mysql基本操作
    二叉树的构建
    synchronized修饰方法和对象的区别
  • 原文地址:https://www.cnblogs.com/yc3120/p/4044670.html
Copyright © 2020-2023  润新知