给出以下代码:
import java.io.File;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
StackPane stackPane = new StackPane();
stackPane.setOnMouseClicked((event) -> {
String path = "audio.ext";
Media media = new Media(new File(path).toURI().toString());
MediaPlayer mp = new MediaPlayer(media);
mp.setAutoPlay(true);
});
stage.setScene(new Scene(stackPane));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
当我点击屏幕时,音频文件(audio.ext
)应播放。我可以获取MP3
个文件和WAV
个文件来播放音频。但是,当我使用M4A
文件尝试相同的代码时,音频无法播放。
我稍微修改了代码以解决问题时发现了一些有趣的案例。
如果我将MediaPlayer
对象(mp
)设为实例变量并在setOnMouseClicked
块中初始化它,则音频将按原样播放,我没有任何问题。
setOnMouseClicked
块的末尾:MediaView mv = new MediaView(mp);
stackPane.getChildren().add(mv);
如果我这样做,那么音频将按原样播放,并且屏幕不会在视觉上发生变化(即,将MediaView
对象添加到StackPane
并不会在视觉上改变它。)
我的问题是:为什么会发生这种情况,是否可以在不使用这些变通办法的情况下播放音频?
我怀疑的是,对象的外部引用是MediaPlayer
工作所必需的。在案例1中,实例变量充当外部参考,在案例2中,StackPane
保留了对MediaView
的引用,而MediaPlayer
又引用了M4A
。但是,这并不能解释为什么只有MP3
个文件而不是WAV
或MediaPlayer
文件才会出现这种情况。由于某种原因,M4A
可能会将require_once('TwitterAPIExchange.php');
$connection = array('oauth_access_token' => 'xxx', 'oauth_access_token_secret' => 'xxx', 'consumer_key' => 'xxx', 'consumer_secret' => 'xxx');
try {
$twitter = new TwitterAPIExchange($connection);
echo 'Connection success <br /> ';
$response = $twitter->buildOauth('https://api.twitter.com/1.1/statuses/update.json', 'POST')->setPostfields(array('status' => 'Test Tweet'))->performRequest();
$json = json_decode($response, true);
if (!empty($json['id_str'])) echo 'Post success: '.$json['id_str'];
}
catch (Exception $ex) {
echo $ex->getMessage();
}
文件视为视频文件而不是音频文件。然而,这是所有猜测,我不确定为什么会发生这种情况。
答案 0 :(得分:2)
当您不存储对象的引用时,Java垃圾收集器可以在引用超出范围时清除它。
来自How Garbage Collection Works:
添加代码时:
MediaPlayer mp = new MediaPlayer(media);
MediaView mv = new MediaView(mp);
stackPane.getChildren().add(mv);
媒体播放器的引用保留在MediaView和StackPane中,因此媒体播放器不会被垃圾回收。但是,如果您没有保留引用的代码,则可以随时对MediaPlayer进行垃圾回收。
另请注意MediaPlayer javadoc:
MediaPlayer的操作本质上是异步的。玩家不准备立即响应命令,直到其状态转换为MediaPlayer.Status.READY,这实际上通常发生在媒体预滚动完成时。
因为操作是异步的,如果你没有存储对MediaPlayer的引用,那么代码可以受race condition的约束,垃圾收集器在MediaPlayer完成播放媒体之前清理MediaPlayer 。根据竞争条件的性质,受其约束的代码的行为是不可预测的,这通常是不期望的特征。
至于为什么播放MP3和WAV文件而你没有保留对MediaPlayer的引用,这可能只是运气。垃圾收集可以在您不再具有对MediaPlayer的引用的任何时间发生。因此,在MediaPlayer中播放未保留引用的Media不是我依赖的行为。相反,最好至少保留对MediaPlayer的引用,直到它完成播放其相关媒体为止。