Android语言基础教程(235)Android创建Started Service实例之继承IntentService输出当前时间:Android后台の时间魔法:IntentService,让你的A

  • 时间:2025-11-23 20:19 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:是时候请出后台任务的“佛系打工仔”了! 嘿,各位在Android世界里摸爬滚打的童鞋们,有没有遇到过这种尴尬:你想让App在后台做点事情,比如每隔一段时间记录个日志、同步点数据,结果要么是写的代码把主线程卡得一动不动,用户直接想摔手机;要么是服务(Service)在后台赖着不走,像个“钉子户”一样耗电,最后被系统无情“清理门户”。 别慌,今天的主角——IntentService,就是来拯救你的

是时候请出后台任务的“佛系打工仔”了!

嘿,各位在Android世界里摸爬滚打的童鞋们,有没有遇到过这种尴尬:你想让App在后台做点事情,比如每隔一段时间记录个日志、同步点数据,结果要么是写的代码把主线程卡得一动不动,用户直接想摔手机;要么是服务(Service)在后台赖着不走,像个“钉子户”一样耗电,最后被系统无情“清理门户”。

别慌,今天的主角——IntentService,就是来拯救你的!它堪称是Android官方为你准备好的“后台任务模范生”。

一、剧情前瞻:Service家族里的“奇葩”与“暖男”

在深入代码之前,我们先来理清人物关系。Android的Service(服务)家族里,主要有两大派系:

Started Service(启动式服务):就像一个没有界面的Activity,通过 startService()方法启动后,它就能在后台独立运行,哪怕你关闭了App,它也能继续“为爱发电”。但是! 它默认是跑在主线程里的。你在主线程里干重活?恭喜你,ANR(应用程序无响应)弹窗正在向你招手。Bound Service(绑定式服务):这个更像是一个“客服”,当有组件(比如Activity)绑定它时,它才出来提供服务。组件都解绑了,它一般也就功成身退了。

而我们今天的主角 IntentService,是 Started Service 的一个“特殊变种”,或者说,是官方帮你写好了最佳实践的子类。它有几个让人爱不释手的“人设”:

自带后台线程:你不需要自己再 new Thread(),它天生就在子线程里处理你的任务,完美避开ANR雷区。工作队列:如果你一次性丢给它多个任务(Intent),它会乖乖地排好队,一个一个按顺序处理,绝不会“手忙脚乱”。干完活就自尽:任务处理完毕,它会自动调用 stopSelf()停止自己,绝不浪费系统一滴电。这种“事了拂衣去,深藏身与名”的品格,简直是模范员工!

所以,对于那些不需要长期运行、不需要同时处理多任务、不需要与界面实时交互的后台活,IntentService就是你的最佳选择!

二、核心代码大揭秘:继承IntentService,施展时间魔法

理论说再多,不如代码来得实在。我们的目标是:创建一个服务,每隔1秒在Logcat里输出当前时间,持续10次。

1. 创建我们的“时间魔法师”类

首先,你得继承 IntentService。最关键的一步是,必须有一个无参构造器,并且必须调用父类的带字符串参数的构造器。这个字符串是你的工作线程的名字,方便你调试。



public class TimeTellerService extends IntentService {
 
    // !!!灵魂所在:这个无参构造器绝对不能少 !!!
    public TimeTellerService() {
        super("TimeTellerServiceWorkerThread"); // 给后台线程起个帅气的名字
    }
 
    // 这是IntentService的核心,所有任务都在这个方法里处理
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        // 这里面的代码已经运行在子线程了,放心大胆地搞事情吧!
        for (int i = 0; i < 10; i++) {
            // 获取当前时间,并格式化成我们熟悉的样子
            String currentTime = new SimpleDateFormat("HH:mm:ss", Locale.getDefault())
                                    .format(new Date());
            
            // 在Logcat里打印出来,TAG用我们服务的类名,好找
            Log.d("TimeTellerService", "当前时间是: " + currentTime);
            
            try {
                // 睡上一秒,模拟耗时操作
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 如果被打断了,就优雅地结束
                Thread.currentThread().interrupt();
                break;
            }
        }
        // 循环结束,onHandleIntent方法返回后,IntentService会自动调用stopSelf()停止服务。
        Log.d("TimeTellerService", "报时结束,深藏功与名~");
    }
}

代码解读:

onHandleIntent(Intent intent):这是你的主战场。所有通过Intent启动这个服务的请求,都会在这里被处理。你传过来的任何数据,都可以通过 intent.getXXXExtra()来获取。 Thread.sleep(1000):这里我们用它来模拟耗时任务。在实际开发中,这里可能是下载文件、解析数据、压缩图片等等。自动停止:注意,我们完全没有写 stopSelf()。这是因为当 onHandleIntent执行完毕(方法返回)后,IntentService内部机制会自动判断任务队列是否为空,如果空了,就自己调用 stopSelf()。简直不要太贴心!

2. 在AndroidManifest.xml里“上户口”

和Activity一样,Service也需要在清单文件里注册,不然系统找不到它。



<application
    ... >
    <!-- 其他组件... -->
 
    <service
        android:name=".TimeTellerService"
        android:enabled="true"
        android:exported="false" /> 
    <!-- exported="false"表示不允许其他应用启动我们这个服务,更安全 -->
</application>

3. 在Activity里“发号施令”

现在,我们可以在Activity里(比如一个按钮的点击事件中)启动这个服务了。



// 假设在一个Activity中
Button startServiceButton = findViewById(R.id.btn_start_service);
startServiceButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 创建一个指向我们服务的Intent
        Intent serviceIntent = new Intent(this, TimeTellerService.class);
        
        // 如果需要,可以通过Intent传递数据
        // serviceIntent.putExtra("KEY_EXTRA_DATA", "some data");
        
        // 魔法启动!
        startService(serviceIntent);
        
        Toast.makeText(this, "已启动后台报时服务,请看Logcat!", Toast.LENGTH_SHORT).show();
    }
});
三、运行效果与深度思考

当你点击按钮后,马上可以看到一个Toast提示,并且UI界面依然丝般顺滑,没有任何卡顿。与此同时,请打开Android Studio的Logcat工具,过滤Tag为 TimeTellerService,你会看到如下美妙的输出:



D/TimeTellerService: 当前时间是: 14:05:01
D/TimeTellerService: 当前时间是: 14:05:02
D/TimeTellerService: 当前时间是: 14:05:03
...
D/TimeTellerService: 当前时间是: 14:05:10
D/TimeTellerService: 报时结束,深藏功与名~

深度分析:为什么是它,它的局限在哪?

优势(再强调一遍)简单粗暴:无需自己管理线程生命周期。自动排队:避免并发编程的复杂性。节能环保:自动停止,不占资源。 局限性(没有银弹!)不能直接与UI交互 onHandleIntent运行在子线程,不能直接更新UI。如果需要,你得用Handler、 runOnUiThread或者LiveData等机制回传给Activity。任务串行执行:这是把双刃剑。如果同时来了10个任务,第9个任务必须等前面8个全部完成,可能会导致延迟。在Android 8.0 (API 26) 及以后受到限制:由于后台执行限制,当App进入后台后,系统可能会很快地停止你的IntentService。对于需要长期在后台执行的任务,现代Android开发更推荐使用 WorkManager
四、结语与升级之路

恭喜你!你已经成功掌握了如何使用IntentService这个“佛系打工仔”来处理后台任务。它就像是你代码世界里的一个自动扫地机器人,你只需要按下启动键( startService),它就会在后台默默地、有条不紊地把你指定的活干完,然后自己回去充电(停止)。

对于大多数轻量级、不紧急、无需实时交互的后台任务,IntentService依然是一个非常优秀和简洁的选择。

但是,学海无涯!随着Android版本的迭代,后台策略越来越严格。如果你的任务需要精确定时在应用退出后依然能可靠运行、或者需要并行处理,那么你的下一个学习目标应该是:

JobIntentService (兼容包提供的,在旧版本上模拟新API行为)WorkManager (当前处理后台任务的“官方终极答案”,能自动适配不同系统版本,非常强大)

不过,无论如何,理解IntentService的工作机制,都是你征服Android后台编程的坚实一步。它教会了你什么是“Started Service”,什么是后台线程管理,什么是“服务自治”。

好了,代码都给你了,赶紧打开Android Studio,把这个“时间魔法师”请到你的项目里跑一圈吧!感受一下后台任务从未如此简单的快乐!

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】Svelte框架结合SpreadJS实现纯前端类Excel在线填报(2025-11-23 22:34)
【系统环境|】在Three.js中使用HDRI贴图作为3D背景和光源(2025-11-23 22:34)
【系统环境|】看完这一篇学会MyBatis就够了(2025-11-23 22:33)
【系统环境|】linux ps命令详解(2025-11-23 22:33)
【系统环境|】Linux日常小知识EFK(2025-11-23 22:32)
【系统环境|】Linux系统的ps命令和top命令介绍(2025-11-23 22:32)
【系统环境|】跟LaoLiu老刘记英语单词——————刘怀勋(2025-11-23 22:31)
【系统环境|】电容的滤波和退耦,真的理解了吗?(2025-11-23 22:31)
【系统环境|】共射放大电路的低频截频计算方法验证(2025-11-23 22:30)
【系统环境|】“谐音梗英文名,看看你的是什么?”(2025-11-23 22:30)
手机二维码手机访问领取大礼包
返回顶部