在非 activity class 中获取原始资源(声音)
Getting raw resource (sound) in non-activity class
我正在尝试创建一个单例 class 来负责播放游戏声音。我用方法 playSound()
创建了一个单例 class GameSounds
。在 res 文件夹中,我有一个带有文件 letter_found.mp3
.
的子文件夹 'raw'
这是GameSounds
的源代码 class 我写的:
import android.app.Application;
import android.content.Context;
import android.media.MediaPlayer;
public class GameSounds extends Application {
private static GameSounds gameSounds = new GameSounds();
private static MediaPlayer soundPlayer;
private static Context mContext;
private static int mySoundId = R.raw.letter_found;
private GameSounds() {
mContext = this;
}
public static GameSounds getInstance() {
return gameSounds;
}
public static void playSound() {
soundPlayer = MediaPlayer.create(mContext, mySoundId);
soundPlayer.start();
}
}
这似乎不起作用,因为我收到以下错误消息:
"java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference"
我不明白为什么会这样。我尝试搜索 Whosebug 但找不到解决方案。
非常感谢help/explanation。
你不应该继承Application
class除非你尝试使用单例模式。因为应用程序是基础 class,它包含所有其他组件,例如活动和服务。
相反,GameSound class 应该包含 Context
对象和适当的构造函数。
示例)
public class GameSounds {
private GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Context context) {
mContext = new WeakReference<>(context);
}
public GameSounds getInstance(Context context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
在这段代码中,有WeakReference<Context>
而不是上下文。 WeakReference 用于防止内存泄漏,因为如果您在activity.
之外有一个实例,就会发生内存泄漏。
要播放声音,执行GameSounds.getInstance(this).playSound();
即可。
如果尝试播放声音时无法提供上下文,实现initialize
方法并在应用程序中调用class就可以了。
public class GameSounds {
private static GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Application context) {
mContext = new WeakReference<>(context);
}
public static void initialize(Application context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
}
public static GameSounds getInstance() {
if (gameSounds == null) {
throw new NullPointerException("You need to initialize this code by GameSound.initialize(this) in application class");
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
在这种情况下,您应该在 class.
中通过 GameSound.initialize(this)
创建 Application class 并初始化 GameSound class
要播放声音,GameSound.getInstance().playSound()
即可。
您可以让一个单例持有一个应用程序 Context
(不是 Activity 上下文),但实际上您必须在使用单例之前设置此上下文,这可以通过抛出异常来强制执行。请参见下面的示例代码。
public class GameSounds {
private static Context sContext;
public static void setContext(Context context) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
// In order to avoid memory leak, you should use application context rather than the `activiy`
context = context.getApplicationContext();
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
sContext = context;
}
private static Context getContext() {
if (sContext != null) {
return (Context)sContext;
}
throw new IllegalStateException("sContext was not set yet! Please call method setContext(Context context) first.");
}
// the rest of other methods. e.g. playSounds()
private static GameSounds gameSounds = new GameSounds();
private GameSounds() {
}
public static GameSounds getInstance() {
return gameSounds;
}
public void playSound() {
Context context = getContext();
soundPlayer = MediaPlayer.create(context, mySoundId);
soundPlayer.start();
}
}
我正在尝试创建一个单例 class 来负责播放游戏声音。我用方法 playSound()
创建了一个单例 class GameSounds
。在 res 文件夹中,我有一个带有文件 letter_found.mp3
.
这是GameSounds
的源代码 class 我写的:
import android.app.Application;
import android.content.Context;
import android.media.MediaPlayer;
public class GameSounds extends Application {
private static GameSounds gameSounds = new GameSounds();
private static MediaPlayer soundPlayer;
private static Context mContext;
private static int mySoundId = R.raw.letter_found;
private GameSounds() {
mContext = this;
}
public static GameSounds getInstance() {
return gameSounds;
}
public static void playSound() {
soundPlayer = MediaPlayer.create(mContext, mySoundId);
soundPlayer.start();
}
}
这似乎不起作用,因为我收到以下错误消息:
"java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference"
我不明白为什么会这样。我尝试搜索 Whosebug 但找不到解决方案。
非常感谢help/explanation。
你不应该继承Application
class除非你尝试使用单例模式。因为应用程序是基础 class,它包含所有其他组件,例如活动和服务。
相反,GameSound class 应该包含 Context
对象和适当的构造函数。
示例)
public class GameSounds {
private GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Context context) {
mContext = new WeakReference<>(context);
}
public GameSounds getInstance(Context context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
在这段代码中,有WeakReference<Context>
而不是上下文。 WeakReference 用于防止内存泄漏,因为如果您在activity.
要播放声音,执行GameSounds.getInstance(this).playSound();
即可。
如果尝试播放声音时无法提供上下文,实现initialize
方法并在应用程序中调用class就可以了。
public class GameSounds {
private static GameSounds gameSounds;
private MediaPlayer soundPlayer;
private WeakReference<Context> mContext;
private int mySoundId = R.raw.letter_found;
private GameSounds(Application context) {
mContext = new WeakReference<>(context);
}
public static void initialize(Application context) {
if (gameSounds == null) {
gameSounds = new GameSounds(context);
}
}
public static GameSounds getInstance() {
if (gameSounds == null) {
throw new NullPointerException("You need to initialize this code by GameSound.initialize(this) in application class");
}
return gameSounds;
}
public void playSound() {
soundPlayer = MediaPlayer.create(mContext.get(), mySoundId);
soundPlayer.start();
}
}
在这种情况下,您应该在 class.
中通过GameSound.initialize(this)
创建 Application class 并初始化 GameSound class
要播放声音,GameSound.getInstance().playSound()
即可。
您可以让一个单例持有一个应用程序 Context
(不是 Activity 上下文),但实际上您必须在使用单例之前设置此上下文,这可以通过抛出异常来强制执行。请参见下面的示例代码。
public class GameSounds {
private static Context sContext;
public static void setContext(Context context) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
// In order to avoid memory leak, you should use application context rather than the `activiy`
context = context.getApplicationContext();
if (context == null) {
throw new IllegalArgumentException("context cannot be null!");
}
sContext = context;
}
private static Context getContext() {
if (sContext != null) {
return (Context)sContext;
}
throw new IllegalStateException("sContext was not set yet! Please call method setContext(Context context) first.");
}
// the rest of other methods. e.g. playSounds()
private static GameSounds gameSounds = new GameSounds();
private GameSounds() {
}
public static GameSounds getInstance() {
return gameSounds;
}
public void playSound() {
Context context = getContext();
soundPlayer = MediaPlayer.create(context, mySoundId);
soundPlayer.start();
}
}