我对java和Android还比较陌生,正在使用Android示例代码MediaBrowserService。
我利用该代码来了解媒体控制器和媒体会话如何协同工作。 回调用于该使用模式。 我还在该示例中看到的是,用户定义的类也使用了回调范式。
我对此的线程限制有疑问。例如,在公共类 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;
}
然后在公共类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 操作都需要在单独的线程上显式执行。因此,回调的线程同步似乎不是大多数人谈论的事情。如果我们在两个不同线程上的操作之间发送回调,则必须这样做。框架设计者之所以采用单线程策略,正是因为线程同步对于大多数程序员来说是一个棘手的主题。
您确实提出了一个有趣的问题,作为回答,以这种方式(通过框架(同步的回调示例是:
AsyncTask
的doInBackground()
和onPostExecute()
方法 .- 凌空抽射
Request
的onResponse()
和onError()
方法 .
但是,这些都不是您所描述类型的真正接口回调。这些是在派生类中重写的虚拟方法。我不得不承认,到目前为止,我从未在Android应用程序开发中看到过在两个线程之间同步的接口回调。