从另一个服务启动一个服务并按值传递

Start a Service from another Service and pass-by-value

提问人:Angelo 提问时间:3/12/2014 更新时间:3/12/2014 访问量:1509

问:

我的 Android 应用程序中有一个服务。在 onStartCommand 期间,我将 Service 对象传递给另一个类。然后,从那里开始,有一个线程在 30 秒后启动另一个服务。它是这样的:

public class FooService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MyClass mc = new MyClass(this);
        mc.testMethod();
        stopSelf();
        return START_NOT_STICKY;
    }
}

这就是 MyClass:

public class MyClass {

    private Service service;

    public MyClass(Service service) {
        this.service = service;
    }

    public void testMethod() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(20*1000);
                    Intent intent = new Intent(service, BarService.class);
                    service.startService(intent);
                }
                catch (Exception e) {
                    // CATCH!
                }
            }
        }).start();
    }
}

现在,正如你所看到的,在 FooService 中,我调用 stopSelf() 并销毁了该 Service 对象。顺便说一句,MyClass 已经获得了按值传递的该服务的副本。20 秒后,我们可以从 MyClass 启动 BarService。我已经测试过了,它有效,但我不明白为什么!我写代码的方式很脏(对我来说)。从被销毁的服务启动另一个服务是否正确?谢谢你的帮助。

Android 服务 按值传递

评论

0赞 shemsu 3/12/2014
参考资料保存。很正常。为此,您应该使用 AlarmManager。
0赞 Angelo 3/12/2014
@SoothSayer 它不是引用(或指针,或其他什么)。Java 是按值传递的,这意味着对象本身被销毁,但即使它没有处于启动状态,我也得到了该服务的副本。这是一个理论问题:从我使用 stopSelf() 销毁的服务启动另一个服务是否正确?我已经实现了一个 AlarmManager,但现在,我每次在 MyClass 中的 Service 对象时都会更新。
0赞 TheLittleNaruto 3/12/2014
将 Handler 与 Messenger 结合使用,并通过活动不断更新您的服务。
0赞 shemsu 3/12/2014
Java 不是一个按值传递的,我的意思是,是的,但它不是那么简单。和 stopSelf() != 已销毁的对象。IMO,从停止的服务开始另一个服务不是一个好主意。有效是因为您的服务已停止但仍然存在。

答:

0赞 CommonsWare 3/12/2014 #1

我已经测试过了,它有效,但我不明白为什么

它现在适用于您测试的环境。它可能无法在所有环境中工作(例如,ROM mods),并且可能无法在明天工作(例如,Android 操作系统更新)。销毁的,例如您停止的服务,不应用于任何用途。碰巧目前您仍然可以使用它来调用以后,但不能保证这种行为。ContextstartService()

从被销毁的服务启动另一个服务是否正确?

不。在这种情况下,我不明白为什么您首先需要两项服务。

我有该服务的副本

不,你没有。

评论

0赞 Angelo 3/12/2014
所以,在这一点上,我认为我正在回过头来混淆按引用传递、按值传递......
0赞 CommonsWare 3/12/2014
@Angelo:stackoverflow.com/questions/40480/is-java-pass-by-reference 简而言之,构造函数中有一个指向对象的指针。该指针是从其原始位置(在服务中)复制(按值传递)的。不会复制基础对象serviceMyClassServicethis
0赞 Angelo 3/12/2014
我读了太多次那个该死的链接:D因此,按值传递意味着复制指针,而不是对象本身。好!因此,即使我调用 stopSelf()(正如 SoothSayer 所指出的那样),Service 对象也不会被销毁,我在 MyClass 中仍然有一个引用,GC 不会销毁它......但它在 Android 环境中不可用。它仍然有效,只是因为对象在我的堆栈中的某个地方,对吧?
1赞 CommonsWare 3/12/2014
@Angelo:您仍然可以提供服务。在 中使用语句,基于 中的额外内容进行分支。ifonStartCommand()Intent
1赞 CommonsWare 3/12/2014
@Angelo:如果一个实例仅由一个实例使用,请使用 .如果一个实例可能被多个组件使用(例如,它是一个单例),请使用检索并使用它,以避免内存泄漏。MyClassServiceServiceMyClassgetApplication()Application