0

我将我的 Android 应用程序的一部分实现为两个本地绑定服务,一个依赖于另一个。(我只bindService()与它们一起使用;从不startService()。)但是,当我绑定具有依赖项的服务时,我会在它自己的依赖项准备好之前获得对它的“绑定”和“连接”引用。这使得对其某些方法的调用失败。如何确保在连接其依赖服务之前不使用我的服务?我可以延迟我的服务的连接直到它自己的依赖项被连接吗?

通常,人们只会获得对已准备好使用的绑定服务的引用,因为onCreate()它们onBind()已经被调用过。但是,当您为服务调用bindService()服务onCreate()A,连接到BonServiceConnected()回调B可以(在我的情况下是!)在连接到之后调用。默认情况下,一切都在同一个(主 UI)线程中运行,因此您不能只在连接返回之前让'等待连接。onServiceConnected()AAonBind()B


我做了一个简单的应用程序来演示这个问题。以下是相关摘录。我的活动加载具有依赖项的服务,ServiceA

public class MainActivity extends Activity {
    private ServiceA serviceA;

    private final ServiceConnection connectionA = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            serviceA = ((ServiceA.Binder) service).getService();
            setGreeting();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            serviceA = null;
        }
    };

    protected void setGreeting() {
        String greeting = serviceA.getGreeting();
        TextView textView = (TextView) findViewById(R.id.greeting);
        textView.setText(greeting);
    }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this, ServiceA.class),
            connectionA, Context.BIND_AUTO_CREATE);
    }

    /* ... */
}

这是ServiceB,这ServiceA取决于:

public class ServiceB extends Service {
    public class Binder extends android.os.Binder {
        public ServiceB getService() {
            return ServiceB.this;
        }
    }

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

    public String getGreeting() {
        return "Hello";
    }
}

这是ServiceA

public class ServiceA extends Service {
    public class Binder extends android.os.Binder {
        public ServiceA getService() {
            return ServiceA.this;
        }
    }

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

    private ServiceB serviceB;

    private final ServiceConnection connectionB = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            serviceB = ((Service1.Binder) service).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            serviceB = null;
        }
    };

    @Override
    public void onCreate() {
        bindService(new Intent(this, ServiceB.class),
            connectionB, Context.BIND_AUTO_CREATE);
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        unbindService(connectionB);
        super.onDestroy();
    }

    public String getGreeting() {
        return serviceB.getGreeting() + "!";
    }
}

我已将这两项服务添加到AndroidManifest.xml. 当我运行它时,serviceB正在null调用serviceA.getGreeting()from setGreeting(),因为connectionB.onServiceConnected()还没有被调用。

有什么方法可以让我connectionA.onServiceConnected()只有在被调用后才能被调用connectionB.onServiceConnected()?或者我怎么能确保我不使用serviceB之前serviceA.serviceB已经设置?


我注意到,如果不是setGreeting()直接调用 in onServiceConnected(),而是直接调用post()到 looper 队列的末尾,问题似乎就消失了:

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
    serviceA = ((ServiceA.Binder) service).getService();
    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            setGreeting();
        }
    });
}

我想这是因为所有onServiceConnected()要进行的调用都恰好在 looper 的队列中,所以通过等待所有当前任务,在被调用serviceA.serviceB时已经准备好。setGreeting()但这对我来说并不可靠。这可靠吗?有没有更可靠的方法可以等到我的服务准备好?

4

0 回答 0