java - Android中不同线程之间的同步回调

标签 java android multithreading concurrency callback

我对 java 和 Android 还比较陌生,正在使用 Android 示例代码 MediaBrowserService。

我利用该代码了解 MediaController 和 MediaSession 如何协同工作。回调用于该使用模式。我在该示例中还看到,用户定义的类也使用回调范例。

我有一个关于线程限制的问题。 例如,在公共(public)类 MusicProvider 中声明如下:

public interface Callback {
void onMusicCatalogReady(boolean success);
}

在同一类中有以下引用:

private void retrieveMediaAsync(Callback callback) {
    initializationLock.lock();
        //...
        //code removed
        //...
        if (callback != null) {
            Log.w(" CB_REF1",":");

            callback.onMusicCatalogReady(mCurrentState == State.INITIALIZED);
        }
    }
}

和:

public void retrieveMedia(final Callback callback) {
        //...
        //code removed
        //...
        Log.w(" CB_REF2",":");
        callback.onMusicCatalogReady(true);
        return;
    }

然后在公共(public)类 MusicService(扩展 MediaBrowserService)中有以下定义:

public void onCreate() {
    //...
    //code removed
    //...
    super.onCreate();
    Log.w(" CB_DEF2",":");
    mMusicProvider.retrieveMedia(new MusicProvider.Callback() {
        @Override
        public void onMusicCatalogReady(boolean success) {

            mState = success ? PlaybackState.STATE_NONE : PlaybackState.STATE_ERROR;
        }
    });

和:

public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
        //...
        //code removed
        //...

        Log.w(" CB_DEF1",":");
        mMusicProvider.retrieveMedia(new MusicProvider.Callback() {
            @Override
            public void onMusicCatalogReady(boolean success) {

                if (success) {
                    loadChildrenImpl(parentMediaId, result);
                } else {
                    updatePlaybackState(getString(R.string.error_no_metadata));
                    result.sendResult(new ArrayList<MediaItem>());
                }
            }
        });

然后我运行应用程序,在 Logcat 窗口中输出以下内容:

03-01 12:19:32.607    1929-1929/com.example.android.mediabrowserservice W/CB_DEF2﹕ :
03-01 12:19:32.794    1929-1929/com.example.android.mediabrowserservice W/CB_DEF2﹕ :
03-01 12:19:32.957    1929-1929/com.example.android.mediabrowserservice W/CB_DEF1﹕ :
03-01 12:19:33.294    1929-2053/com.example.android.mediabrowserservice W/CB_REF1﹕ :
03-01 12:19:45.329    1929-1929/com.example.android.mediabrowserservice W/CB_DEF2﹕ :
03-01 12:19:45.347    1929-1929/com.example.android.mediabrowserservice W/CB_DEF1﹕ :
03-01 12:19:45.426    1929-2033/com.example.android.mediabrowserservice W/CB_REF1﹕ :
03-01 12:19:45.428    1929-2033/com.example.android.mediabrowserservice W/CB_REF1﹕ :
03-01 12:19:47.622    1929-1929/com.example.android.mediabrowserservice W/CB_DEF2﹕ :
03-01 12:19:47.643    1929-1929/com.example.android.mediabrowserservice W/CB_DEF1﹕ :
03-01 12:19:47.732    1929-2053/com.example.android.mediabrowserservice W/CB_REF1﹕ :
03-01 12:19:47.734    1929-2033/com.example.android.mediabrowserservice W/CB_REF1﹕ :

所以我可以看到(并且有点理解)如何通过将特定定义注册为回调来根据需要重新定义回调函数。

我的问题与多线程相关的行为有关。

注册不同回调方法的能力是否意味着所有这些注册都必须发生在与回调调用相同的线程中,以确保调用回调时回调注册不处于某个中间状态?

如果不是这种情况,那么在我看来,当回调被调用时,注册回调的指令可能处于某种中间状态,我不确定这将如何在 Android 环境中处理。

感谢您考虑我的问题。 吉姆

最佳答案

Android遵循单线程模型,也就是说,所有与UI相关的操作都只发生在主线程上,所有非UI操作都需要显式地在单独的线程上执行。因此,回调的线程同步并不是大多数人谈论的话题。如果我们在两个不同线程上的操作之间发送回调,则有必要这样做。框架设计者采用单线程策略正是因为线程同步对大多数程序员来说是一个棘手的问题。

您确实提出了一个有趣的问题,作为回答,以这种方式(由框架)同步的回调示例是:

  • AsyncTaskdoInBackground()onPostExecute() 方法。
  • Volley RequestonResponse()onError() 方法。

但是,这些都不是您所描述类型的真正接口(interface)回调。这些是在派生类中重写的虚方法。我必须承认,到目前为止,我从未在 Android 应用程序开发中看到过在两个线程之间同步的接口(interface)回调。

关于java - Android中不同线程之间的同步回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28797825/

相关文章:

java - 将 Spring Boot 与 Neo4J 结合使用 : Updating node creates duplicate node

java - Webview自动输入密码的方法

android - 如何让 StringRequest Volley 等待响应?

java - 尽管从同步上下文调用了notifyAll(),但仍存在 IllegalMonitorStateException

c++ - 以符合 C++ 标准的方式实现 std::malloc

java - 为什么等待线程不会永远等待

java - java.util.logging 配置属性文件中的 log4j.appender.console.target 等效项

java - 在运行时增强 java 对象

android - 如何在数据库中插入地理点值?

c - 使用多线程读取文件