android线程实现后台设置时间自动更新

如果你的应用需要请求服务器,解析进行展示,那么你可能会需要实现自动更新问题,既然是后台更新,那你肯定联想到服务,因为服务service通常是在后台执行的,但是,咱们有必要用到服务吗?
服务地方:
后台播放音乐—打开播放器界面,点击某一首音乐,返回键退出,音乐还在播放,用的service。

后台下载大文件。
http://blog.csdn.net/mynameishuangshuai/article/details/51821662
解释非常好:
http://ticktick.blog.51cto.com/823160/1547032/
首先,需要了解Service的几个特点。

1Thread 是程序执行的最小单元,
    它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。

2、被用来执行长时间的后台任务。
默认情况下Service是运行在主线程中的。

(1) 默认情况下,Service其实是运行在主线程中的,如果需要执行复杂耗时的操作,必须在Service中再创建一个Thread来执行任务。

(2) Service的优先级高于后台挂起的Activity,当然,也高于Activity所创建的Thread,因此,系统可能在内存不足的时候优先杀死后台的Activity或者Thread,而不会轻易杀死Service组件,即使被迫杀死Service,也会在资源可用时重启被杀死的Service

其实,Service和Thread根本就不是一个级别的东西,Service是系统的四大组件之一,Thread只是一个用来执行后台任务的工具类,它可以在Activity中被创建,也可以在Service中被创建。因此,我们其实不应该讨论该使用Service还是Thread,而是应该讨论在什么地方创建Thread。

典型的应用中,它可以在以下三个位置被创建,不同的位置,其生命周期不一样,所以,我们应该根据该Thread的目标生命周期来决定是在Service中创建Thread还是在Activity中创建它。

1) 在Activity中被创建


这种情况下,一般在onCreate时创建,在onDestroy()中销毁,否则,Activity销毁后,Thread是会依然在后台运行着,占用内存,并且再次onreate()这个activity,thread重新创建。

这种情况下,Thread的生命周期即为整个Activity的生命周期。所以,在Activity中创建的Thread只适合完成一些依赖Activity本身有关的任务,比如定时更新一下Activity的控件状态等。

核心特点:该Thread的就是为这个Activity服务的,完成这个特定的Activity交代的任务,主动通知该Activity一些消息和事件,Activity销毁后,该Thread也没有存活的意义了,所以需要再ondestory()中销毁这个thread,或者通过boolean控制run()方法的执行。
2)在Application中被创建


这种情况下,一般自定义Application类,重载onCreate方法,
并在其中创建Thread,当然,也会在onTerminate()方法中销毁Thread,
否则,如果Thread没有退出的话,即使整个Application退出了,
线程依然会在后台运行着。


这种情况下,Thread的生命周期即为整个Application的生命周期。
所以,在Application中创建的Thread,
可以执行一些整个应用级别的任务,比如定时检查一下网络连接状态等等。


核心特点:该Thread的终极目标是为这个APP的各个Activity服务的,包括完成某个Activity交代的任务,主动通知某个Activity一些消息和事件等(可以使用handler),APP退出之后该Thread也没有存活的意义了。


以上这两种情况下,Thread的生命周期都不应该超出整个应用程序的生命周期,也就是,整个APP退出之后,Thread都应该完全退出,这样才不会出现内存泄漏或者僵尸线程。那么,如果你希望整个APP都退出之后依然能运行该Thread,那么就应该把Thread放到Service中去创建和启动了。
3)在Service中被创建


这是保证最长生命周期的Thread的唯一方式,只要整个Service不退出,Thread就可以一直在后台执行,一般在Service的onCreate()中创建,在onDestroy()中销毁。


所以,在Service中创建的Thread,适合长期执行一些独立于APP的后台任务,比较常见的就是:在Service中保持与服务器端的长连接。


核心特点:该Thread可以为APP提供一些“服务”或者“状态查询”,但该Thread并不需要主动通知APP任何事件,甚至不需要知道APP是谁。


总之,我们不是要考虑该用Thread或者该用Service,而是应该为Thread选择合适的生命周期,这就是我对Service和Thread的思考和理解。

线程销毁
其实不能说线程销毁,只能说线程已经不会执行了,不做run()里面方法,通俗点,死掉了。
http://blog.csdn.net/lincyang/article/details/49494555

1、设置标记

2、中断interrupt()
另一种情况,线程只是在执行单一的耗时的任务(没有设置标记tag),方法一就失效了。而线程中的stop方法是不推荐使用的,那用什么办法才能终止它?
目前使用interrupt方法将其“打断”,进而令其立即退出run方法,进入Dead状态。

3、stop 不推荐

http://blog.csdn.net/lincyang/article/details/49494555

子线程和UI主线程通信
1、Handler + Message
2、View.post view.postDelay

try {
    //InputStream inputStream = getResources().openRawResource(R.id.xxx);  
    InputStream inputStream = assetManager.open("android/xxx.png");
    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
    mMainLayout.post(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "set image");
            mMainLayout.setBackground(new BitmapDrawable(bitmap));
        }
    });
    inputStream.close();
} catch (IOException e) {
    e.printStackTrace();
}
源码:
那么view.post(Runnable r)是怎么工作的呢,源码如下:
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}

由此可见,view获取到关联线程(即UI线程,因为只有UI线程才能创建view)的handler,然后调用该handler的post方法,即把这个任务封装成一个消息post到主线程的消息队列中,然后等待执行。

3、handler.post
handler.postdelay

Handler发送消息的过程仅仅是向消息队列中插入了一条消息,MessagQueue的next方法一会返回这条消息给Looper,Looper收到消息后就开始处理了。最终消息由Looper交由Handler处理,即Handler的dispatchMessage方法会被调用。dispatchMessage方法的源码如下:

public void dispatchMessage(Message msg){
if(msg.callback != null){
handleCallback(msg);
}else{
if(mCallback != null){
if(mCallback.handleMessage(msg)){
return ;
}
}
handleMessage(msg);
}
}
runnable.run()方法逻辑的执行际上是在runnable所在的线程中的执行的,runnable并不会新开辟一个子线程。runnable中的逻辑实际上是在主线程中执行的,要是runnable逻辑出现阻塞,那么主线程也会相应的被阻塞。而Thread就是完全开辟了一个子线程了,线程ID发生了变化。


回到开头提到的问题,handler.post方法可以进行UI修改,但是里面的逻辑是在主线程中执行的,要是有耗时操作,会阻塞主线程,导致点击事件无响应等,所以handler.post可以用作修改UI,但是不应该用Handler.post执行一些复杂的逻辑。

易出错点:
子线程不能更新UI
Handler handler属于子线程的

package com.example.helloandroid;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.TextView;

public class MainActivity extends Activity {
    TextView tv;
    int i = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.textView1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Looper.prepare();
                    Thread.sleep(1000);
                    Handler handler = new Handler();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText("post " + i++);// 更新UI
                        }
                    });
                    Looper.loop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

可以这样子:
Handler handler = new Handler(Looper.getMainLooper());
拿到主线程handler,再自己给自己发信息!!!!

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                //  Looper.prepare();
                    while (true) {
                        Thread.sleep(1000);
                        Handler handler = new Handler(Looper.getMainLooper());
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                tv.setText("post " + i++);// 更新UI
                            }
                        });                     
                    }

                //  Looper.loop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
Handler
Messagequeue
Looper 的 prepare()、loop()

application完全退出app:
http://blog.csdn.net/zeus_9i/article/details/7259881
onCreate 在创建应用程序时创建

onTerminate 当终止应用程序对象时调用,不保证一定被调用,当程序是被内核终止以便为其他应用程序释放资源,那

么将不会提醒,并且不调用应用程序的对象的onTerminate方法而直接终止进 程

onLowMemory 当后台程序已经终止资源还匮乏时会调用这个方法。好的应用程序一般会在这个方法里面释放一些不必

要的资源来应付当后台程序已经终止,前台应用程序内存还不够时的情况。

onConfigurationChanged 配置改变时触发这个方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值