[英]Getting raw resource (sound) in non-activity class
我正在嘗試創建一個負責播放游戲聲音的單例類。 我使用playSound()
方法創建了一個單例類GameSounds
。 在res文件夾中,我有一個子文件夾'raw',其文件為letter_found.mp3
。
這是我編寫的GameSounds
類的源代碼:
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:嘗試在空對象引用上調用虛擬方法'android.content.res.Resources android.content.Context.getResources()'”
我不明白為什么會這樣。 我試圖搜索Stackoverflow,但找不到解決方案。
任何幫助/說明,我們將不勝感激。
除非嘗試使用Singleton模式,否則不應繼承Application
類 。 因為Application是基類,所以它包含所有其他組件,例如活動和服務。
相反,GameSound類應包含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>
而不是Context。 WeakReference用於防止內存泄漏,因為如果活動之外有一個實例,則可能發生內存泄漏。
要播放聲音,請執行GameSounds.getInstance(this).playSound();
很好
如果嘗試播放聲音時Context無法提供,則可以實現initialize
方法並在Application類中調用可以。
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();
}
}
在這種情況下,您應該創建Application類,並通過Application類中的GameSound.initialize(this)
初始化GameSound類。
要播放聲音,可以使用GameSound.getInstance().playSound()
。
您可以讓一個Singleton持有一個應用程序Context
(NOT Activity上下文),但是實際上您必須在使用Singleton之前設置此上下文,該Singleton可以通過引發異常來強制執行。 請參見下面的示例代碼。
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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.