Android生命周期:Activity,Thread,服务,广播,fragment

Activity的生命周期:


1:程序正运行着突然跳出一个ThemeTranslucent或者DialogActivity,那么当前Activity只是onPause ,恢复的时候onResume

2:程序正运行着突然来电话了,如果中止的时候新出的一个Activity是全屏的那么:onPause->onStop,恢复的时候onRestart->onStart->onResume

3:程序正运行着突然跳出1一样的东西,但是太消耗内存,以至于内存不足,刚暂停的Activity就会被系统杀死,等到用户返回的时候,再重新onCreate();

4:栈中运行了很多的Activity,当内存不足的时候,会被系统杀死掉,用户按返回键导航回来的时候,系统再重新onCreate();


详细介绍一下这几个方法中系统在做什么以及我们应该做什么:


onCreate:
在这里创建界面 ,做一些数据的初始化工作
onStart:
用户可见不可交互 的
onResume:
变成和用户可交互的
onPause:
可见但不可交互 的,系统会停止动画等消耗CPU的事情,应该在这里保存你的一些数据,因为这个时候
你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动
onstop:
变得不可见 ,被下一个activity覆盖了
onDestroy:
这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。


onPause
,onstop, onDestroy,三种状态 下 activity都有可能被系统干掉




Thread线程的生命周期:

 新建(new Thread)

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。例如:Thread  t=new Thread();

就绪(runnable)
线程已经被启动(例如:t.start()),正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。

运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)


Service的生命周期


 onCreate -- onStart -- onDestroy -- onBind 


1). 被启动的服务的生命周期如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStartCommand()将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此只需要一次stopService调用)。

该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的storSelf方法。当然如果系统资源不足,android系统也可能结束服务。

 

2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStartCommand()方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。(也就是Activity结束之前没有解除绑定,程序会报错,但是不会崩溃)

 

3). 被启动又被绑定的服务的生命周期如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStartCommand()便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。及同时使用解绑和停止。

 

4). 当服务被停止时清除服务当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

 

特别注意:

1、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定;

2、你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService; 

3、同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序。

4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。



BroadcastReceiver生命周期

 

运行原理很简单如下图:


每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 所以

BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR 的对话框 .

不能在里面开子线程解决这个问题,因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束

BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的

所在进程很容易在系统需要内存时被优先杀死 , 那么正在工作的子线程也会被杀死 

解决方法:

如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 。也可以跳转Activity,在Activity里面开线程做耗时工作。

比如:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("android.hjnote.ALARM_ACTION")) {
            Intent noteList = new Intent(context, AlarmActivity.class);
            noteList.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(noteList);
        }
    }
} 




Fragment的生命周期





与Activity生命周期的对比


     


 fragment真正的onResume和onPause方法:http://blog.csdn.net/jav_imba/article/details/47417853


实践发现,fragment与activity有很大的不同,activity从用户眼中消失,调用的一系列的方法,但是fragment就没有那么明显了,比如viewpage+fragment的情况下,从fragment1滑动到fragment2,并不是fragment1一不在用户的眼皮下就会执行onPause,


Android v4包下的viewpager,为了让用户在切换过程中不会卡顿,谷歌官方默认当创建第一个fragment方法时回创建第二个fragment以确保用户滑动时第二个view已经被创建,保持viewPager的平滑滑动效果

为了解决判断是否fragment当前显示问题,可以在fragment重写 setUserVisibleHint(boolean isVisibleToUser)

在fragment添加log日志

[java]  view plain  copy
  1. public class Fragment1 extends Fragment {  
  2.     private static final String TAG = "Fragment1";  
  3.   
  4.     @Override  
  5.     public void onAttach(Activity activity) {  
  6.         super.onAttach(activity);  
  7.         L.v(TAG, "onAttach");  
  8.     }  
  9.   
  10.     @Override  
  11.     public void setUserVisibleHint(boolean isVisibleToUser) {  
  12.         L.v(TAG, "setUserVisibleHint " + isVisibleToUser);  
  13.     }  
  14.   
  15.     @Override  
  16.     public void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         L.v(TAG, "onCreate");  
  19.     }  
  20.   
  21.     @Override  
  22.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  23.         L.v(TAG, "onCreateView");  
  24.         View view = inflater.inflate(R.layout.fragment_layout,null);  
  25.         TextView tv = (TextView) view.findViewById(R.id.tv1);  
  26.         tv.setText(TAG);  
  27.         return view;  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
  32.         super.onActivityCreated(savedInstanceState);  
  33.         L.v(TAG,"onActivityCreated");  
  34.     }  
  35.   
  36.     @Override  
  37.     public void onResume() {  
  38.         super.onResume();  
  39.         L.v(TAG, "onResume()");  
  40.     }  
  41.   
  42.     @Override  
  43.     public void onPause() {  
  44.         super.onPause();  
  45.         L.v(TAG,"onPause");  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onStop() {  
  50.         super.onStop();  
  51.         L.v(TAG,"onStop");  
  52.     }  
启动activity打印日志如下:

08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-11 11:33:36.157    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()

当切换到第二个fragment时打印日志:

08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onAttach
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreate
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onResume()

可见当fragment显示时会调用方法 setUserVisibleHint中的isVisibleToUser = true ,当fragment被切换隐藏时 isVisibleToUser = false;

第一次setUserVisibleHint 方法 isVisibleToUser = false 但其实这个时候只是还未初始化,并不是用户已经浏览界面准备离开,于是这里我们需要一个辅助标记变量具体代码如下:

/**
 * 判断是否是初始化Fragment 
 */
private boolean hasStarted = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
    if (isVisibleToUser) {
        hasStarted = true;
        L.v(TAG,"开始界面");
    } else {
        if (hasStarted) {
            hasStarted = false;
            L.v(TAG,"结束界面");
        }
    }
}  



 plain

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值