簡體   English   中英

在非活動類中獲取原始資源(聲音)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM