绑定服务和活动之间的IBinder

时间:2017-09-12 06:36:03

标签: android android-intent

也许我只是累了。但是我很难理解IBinder接口的工作原理。

服务有一个方法调用onBind(Intent intent),它将某种形式的IBinder传递给绑定活动。

我在苦苦挣扎的是如何形象化。 IBinder对象是服务和活动之间的管道,以便活动可以直接与服务交互吗?或者是IBinder是一个传递给活动的对象,该活动中包含来自服务的信息(类似于意图)?

编辑:我的想法是能够从绑定活动中调用getSomeData函数。或者更确切地说,想法是让mSomeData与活动对话。

我正在使用以下类,我试图找出从服务中获取活动请求数据的最佳方法(如果需要,可以序列化,但不是)。

public class MainService extends Service{

    private CustomBinder mIBinder;
    private SomeDataObject mSomeData;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mIBinder = new CustomBinder();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public CustomBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    // This is auto generated and I havent changed it yet. I am not
    // Experiencing errors as this is not designed to run yet.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    public final SomeDataObject getSomeData(){
        return mSomeData;
    }

    class SomeBinder extends MainEngineBinder{
        // All the Auto Generated Stuff
    }
}

1 个答案:

答案 0 :(得分:0)

您无需了解IBinder的工作原理。只是将Binder(不是IBinder)子类化,并将一些方法添加到Binder子类中。可以从绑定到服务的活动中调用这些方法。

在您的情况下,最简单的方法是让内部类扩展Binder,然后内部类将能够从您的服务访问方法/字段并将它们返回到活动。你看起来像是在使用类似于Android documentation on bound services的模板,所以这里是文档中的例子 - 在这种情况下,所有绑定器都会公开一个getter来获取服务本身,并且调用者只需调用方法直接在服务上

public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

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

    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}

调用者调用bind()需要将IBinder强制转换为LocalService.LocalBinder。在这种情况下,IBinder既不是管道也不是类似意图的对象;它是一个普通的Java风格的界面。

请注意,如果您做IPC,所有这一切都适用。 The documentation表示在这种情况下(相同的应用程序,相同的进程)调用是一个普通的Java调用 - 你可以传递对象,引用,无论你喜欢什么,因为一切都在同一个进程中。

请注意,IPC,管道,编组,序列化等都是不必要的(除非您希望从其他应用程序调用您的服务或使用多进程应用程序)。 Android服务甚至不在单独的线程中运行,除非您显式启动新线程,并且没有它的“自己的”线程或进程 - 对绑定器或服务对象本身的所有调用都在与调用者相同的线程中进行

在您的情况下,Android文档中的确切示例似乎是最好的方法。