🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

3回答

1538閲覧

viewPagerでのタブ切替時にRecyclerViewを表示し直したい

jun74

総合スコア338

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2019/10/09 14:03

前提・実現したいこと

viewPagerでタブ切替を行い、Fragmentを切り替える画面があります。
それぞれにリサイクルビューがあります。
タブの切替えではFragmentの「onResume」は実行されません。

viewPagerでタブを切替時に「SoundAdapter.mPlayStop()」で音楽を停止し、「notifyDataSetChanged()」で「onBindViewHolder」の「再生ボタン設定」を行いたいです。
しかし、staticでは「notifyDataSetChanged()」は呼べないとエラーになります。

タブ切替時に「再生ボタン設定」を行う方法は何か無いでしょうか?

viewPagerでのタブ切替時にRecyclerViewを表示し直す、または親のFragmentの表示のし直しでも良いので何か方法があれば、よろしくお願いいたします。

該当のソースコード

MainActivity.java

java

1 //ビューページャータブ切替判定 2 viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 3 //ビューページャータブ選択判定 4 @Override 5 public void onPageSelected(int position) { 6 //ミュージックプレイヤー解放 7 SoundAdapter.mPlayStop(); 8 } 9 });

SoundAdapter.java(リサイクルビューアダプター)

java

1 @Override 2 public void onBindViewHolder(final ItemViewHolder holder, final int position) { 3 onBind = true; 4 5 //行の値設定 6 holder.rb_sound.setChecked(soundList.get(position).m_rb_sound); 7 holder.t_sound_name.setText(soundList.get(position).m_t_sound_name); 8 9 //再生ボタン設定 10 if(playFlg){ 11 if(playPosition == position){ 12 holder.t_play.setText(R.string.playStop_name); 13 }else{ 14 holder.t_play.setText(R.string.play_name); 15 } 16 }else{ 17 holder.t_play.setText(R.string.play_name); 18 } 19 20 onBind = false; 21 } 22 23 //ミュージックプレイヤー解放 24 public static void mPlayStop() { 25 if(playFlg){ 26 // アラーム音が再生されていれば停止する 27 if(mPlayer.isPlaying()) { 28 mPlayer.stop(); // 停止 29 } 30 31 // フォーカスを明け渡す(他のアプリの音楽を停止を解除) 32 adm.abandonAudioFocus(afChangeListener); 33 34 // メディアプレイヤー を解放する 35 if(mPlayer != null){ 36 mPlayer.reset(); 37 mPlayer.release(); 38 mPlayer = null; 39 } 40 41 playFlg = false; 42 } 43 //リサイクルビュー更新 44 notifyDataSetChanged(); //staticだと駄目となる!! 45 }

補足情報(FW/ツールのバージョンなど)

Android Studio3.4
APIレベル14から28まで対象

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2019/10/09 18:41

SoundAdapter の全文をご提示願えますでしょうか.
guest

回答3

0

ご提示されたコードが一部のため, 想像でコードを修正してみました.
単一の PlayerManager インスタンスを必要な個所で使用している他, play/stop 時には PlayerManager.PlayerListener によって通知し, SoundAdapter はそれを受けて行の特定・notify(再表示) しています.

SoundAdapter は過去のご質問のコードから拝借しています.
SoundData の m_sound の型が分からなかったので, Uri としました.
Globals による context の取得も, 普通に上位からの指定にしました.

コードを切り貼りしただけで, 動作は確認していません

MainActivity(一部)

java

1 final PlayerManager playerManager = new PlayerManager(this); 2 3 List<SoundData> alarmList = new ArrayList<>(); //データの設定は省略 4 SoundAdapter alarmAdapter = new SoundAdapter(this, playerManager, alarmList); 5 //alarmAdapter は alarmFragment の RecyclerView に設定 6 7 List<SoundData> musicList = new ArrayList<>(); //データの設定は省略 8 SoundAdapter musicAdapter = new SoundAdapter(this, playerManager, musicList); 9 //musicAdapter は musicFragment の RecyclerView に設定 10 11 //ビューページャータブ切替判定 12 viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 13 //ビューページャータブ選択判定 14 @Override 15 public void onPageSelected(int position) { 16 //ミュージックプレイヤー解放 17 try { 18 playerManager.stop(); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 } 23 });

SoundAdapter(一部想像)

java

1//サウンドリサイクルビューアダプター 2public class SoundAdapter extends RecyclerView.Adapter<SoundAdapter.ItemViewHolder> implements PlayerManager.PlayerListener { 3 //使途不明 4 private boolean onBind; 5 int alarmType; 6 String alarmSound; 7 String musicSound; 8 int alarmPosition; 9 int musicPosition; 10 int chekPosition; 11 int playPosition; 12 13 private PlayerManager playerManager; 14 private List<SoundData> soundList; 15 16 @Override 17 public void onPlay(Uri sound) { 18 int index = search(sound); 19 if(index >= 0) notifyItemChanged(index); 20 } 21 @Override 22 public void onStop(Uri sound) { 23 int index = search(sound); 24 if(index >= 0) notifyItemChanged(index); 25 } 26 private int search(Uri sound) { 27 for(int i=0; i<soundList.size(); i++) if(soundList.get(i).m_sound.equals(sound)) return i; 28 return -1; 29 } 30 31 static class ItemViewHolder extends RecyclerView.ViewHolder { 32 LinearLayout row_layout; 33 RadioButton rb_sound; 34 TextView t_sound_name; 35 TextView t_play; 36 ItemViewHolder(View v){ 37 super(v); 38 row_layout = (LinearLayout)v.findViewById(R.id.row_layout); 39 rb_sound = (RadioButton) v.findViewById(R.id.rb_sound); 40 t_sound_name = (TextView)v.findViewById(R.id.t_sound_name); 41 t_play = (TextView)v.findViewById(R.id.t_play); 42 } 43 } 44 45 SoundAdapter(Context context, PlayerManager playerManager, List<SoundData> soundList){ 46 this.playerManager = playerManager; 47 this.soundList = soundList; 48 49 //設定画面初期値設定 50 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); 51 52 //アラームタイプ取得 53 alarmType = sharedPreferences.getInt("alarmType", 0); 54 //アラーム音取得 55 alarmSound = sharedPreferences.getString("alarmSound", ""); 56 //ミュージック音取得 57 musicSound = sharedPreferences.getString("musicSound", ""); 58 //アラームポジション取得 59 alarmPosition = sharedPreferences.getInt("alarmPosition", 0); 60 //ミュージックポジション取得 61 musicPosition = sharedPreferences.getInt("musicPosition", 0); 62 63 playerManager.addPlayerListener(this); 64 } 65 66 @Override 67 public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType){ 68 View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.sound_row, parent, false); 69 return new ItemViewHolder(v); 70 } 71 72 @Override 73 public void onBindViewHolder(final ItemViewHolder holder, final int position) { 74 onBind = true; 75 76 //行の値設定 77 holder.rb_sound.setChecked(soundList.get(position).m_rb_sound); 78 holder.t_sound_name.setText(soundList.get(position).m_t_sound_name); 79 80 //再生ボタン設定 81 if(soundList.get(position).m_sound.equals(playerManager.getLastPlayedSound())){ 82 holder.t_play.setText(R.string.playStop_name); 83 }else{ 84 holder.t_play.setText(R.string.play_name); 85 } 86 87 //再生ボタンクリック 88 holder.t_play.setOnClickListener(new View.OnClickListener() { 89 @Override 90 public void onClick(View v) { 91 //アラームタイプ判定 92 if(alarmType == 0){ 93 chekPosition = alarmPosition; 94 }else{ 95 chekPosition = musicPosition; 96 } 97 //再生、停止処理 98 try { 99 if(soundList.get(position).m_sound.equals(playerManager.getLastPlayedSound())) { 100 playerManager.stop(); 101 } else { 102 playerManager.play(soundList.get(position).m_sound); 103 } 104 } catch (IOException e) { 105 e.printStackTrace(); 106 } 107 //再生ポジション設定 108 playPosition = position; 109 } 110 }); 111 112 onBind = false; 113 } 114 115 @Override 116 public int getItemCount() { 117 return soundList.size(); 118 } 119}

PlayerManager

java

1public class PlayerManager { 2 private Context context; 3 private MediaPlayer mediaPlayer; 4 private AudioManager audioManager; 5 private AudioManager.OnAudioFocusChangeListener afChangeListener; 6 7 private Uri lastPlayedSound; 8 9 interface PlayerListener { 10 void onPlay(Uri path); 11 void onStop(Uri path); 12 } 13 private List<PlayerListener> playerListenerList = new ArrayList<>(); 14 15 public void addPlayerListener(PlayerListener l) { 16 playerListenerList.add(l); 17 } 18 public void removePlayerListener(PlayerListener l) { 19 playerListenerList.remove(l); 20 } 21 protected void firePlay(Uri path) { 22 for(PlayerListener l : playerListenerList) l.onPlay(path); 23 } 24 protected void fireStop(Uri path) { 25 for(PlayerListener l : playerListenerList) l.onStop(path); 26 } 27 28 public PlayerManager(Context context) { 29 this.context = context; 30 31 // AudioManagerを取得する 32 audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 33 34 //オーディオフォーカスのコールバック 35 afChangeListener = new AudioManager.OnAudioFocusChangeListener() { 36 public void onAudioFocusChange(int focusChange) { 37 //フォーカスを完全に失ったら 38 if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 39 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {//一時的なフォーカスロスト 40 } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {//通知音とかによるフォーカスロスト(ボリュームを下げて再生し続けるべき) 41 } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {//フォーカスを再度得た場合 42 } 43 } 44 }; 45 } 46 47 //再生処理 48 public void play(Uri sound) throws IOException { 49 if(sound == null) throw new IllegalArgumentException(); 50 if (mediaPlayer != null) stop(); 51 52 // 現在のメディア音量を表示する 53 // 現在の音量を取得する 54 int ringVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 55 // 音量を設定する 56 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, ringVolume, AudioManager.FLAG_SHOW_UI); 57 58 // フォーカスを排他的に奪う(他のアプリの音楽を停止) 59 audioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE); 60 61 mediaPlayer = new MediaPlayer(); 62 63 //アラーム音設定 64 mediaPlayer.setDataSource(context, sound); // 音声を設定 65 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // ミュージックボリュームで再生 66 mediaPlayer.setLooping(true); // ループ再生を設定 67 mediaPlayer.prepare(); // 音声を読み込み 68 69 //アラーム音再生 70 mediaPlayer.start(); // 再生 71 72 lastPlayedSound = sound; 73 firePlay(sound); 74 } 75 76 //停止処理 77 public void stop() throws IOException { 78 if(mediaPlayer == null) return; 79 80 // フォーカスを明け渡す(他のアプリの音楽停止を解除) 81 audioManager.abandonAudioFocus(afChangeListener); 82 83 // アラーム音が再生されていれば停止する 84 if (mediaPlayer.isPlaying()) { 85 mediaPlayer.stop(); // 停止 86 } 87 88 // メディアプレイヤー を解放する 89 mediaPlayer.reset(); 90 mediaPlayer.release(); 91 mediaPlayer = null; 92 93 Uri sound = lastPlayedSound; 94 lastPlayedSound = null; 95 fireStop(sound); 96 } 97 98 public Uri getLastPlayedSound() { 99 return lastPlayedSound; 100 } 101}

投稿2019/10/10 15:13

編集2019/10/10 15:24
jimbe

総合スコア13202

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun74

2019/10/12 10:41

反応が遅れて申し訳ありません。 只今、無事インスタンスの対応完了しました! ありがとうございました。
guest

0

ベストアンサー

androidx.fragment:fragment:1.1.0-alpha07 以降をお使いであれば、FragmentPagerAdapterもしくはFragmentStatePagerAdapterの第2引数にBEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENTを渡すことでページの切替時にアクティブなページのonResumeメソッドが呼ばれるようになります。

それ以前のものをお使いであれば、setUserVisibleHintが代わりに呼ばれるので使えるはずです。

参考記事: setUserVisibleHintのdeprecatedとsetMaxLifecycle


余談ですが、オブジェクト間の通知のためだけにメソッドをstaticで宣言するのはオブジェクト指向の考え方に反するアンチパターンなので避けた方がいいと思います。

投稿2019/10/10 11:55

編集2019/10/10 11:55
kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun74

2019/10/10 13:37

いつもありがとうございます! androidxにはまだしてないので、setUserVisibleHintで対応出来ました。 staticは避けた方が良いですよね。。 SoundAdapter.mPlayStop()がstaticで残ってしまい悩み中です。。
guest

0

それぞれのFragmentにRecyclerViewを再度表示し直す処理を作り、解決しました。
もう少しスマートな解決方法がありそうな気もするので解決済にはしないで回答募集を継続します。

MainActivity.java

java

1 //ビューページャータブ切替判定 2 viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 3 //ビューページャータブ選択判定 4 @Override 5 public void onPageSelected(int position) { 6 //ミュージックプレイヤー解放 7 SoundAdapter.mPlayStop(); 8 9 if(position == 0){ 10 //アラーム音選択フラグメントのリサイクルビュー再描写 11 AlarmFragment.reRecyclerView(); 12 }else{ 13 //音楽音選択フラグメントのリサイクルビュー再描写 14 MusicFragment.reRecyclerView(); 15 } 16 } 17 });

AlarmFragment.java

java

1 //リサイクルビュー再描写 2 public static void reRecyclerView() { 3 //アラームポジション取得 4 alarmPosition = sharedPreferences.getInt("alarmPosition", 0); 5 //ラジオボタンチェック位置へ移動 6 mRecyclerView.scrollToPosition(alarmPosition); 7 //リサイクルビュー表示 8 mRecyclerView.setAdapter(mAdapter); 9 }

投稿2019/10/09 16:22

jun74

総合スコア338

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2019/10/10 03:45

SoundAdapter が, RecyclerView へのデータ管理のほかに, プレイヤーの動作まで(static で)管理しているのが原因と思います. プレイヤーの管理を別クラス(例えば PlayManager クラス)とし, そのオブジェクトへの参照をアダプタが持って play/stop の依頼( play(String name) 等)をすると同時に, 新たにリスナ(例えば PlayManager.PlayListener )を定義してアダプタに実装・登録し, 再生・停止毎に情報(例えば再生/停止した名前)をアダプタに通知するようにすれば, アダプタ側はその情報からどの行のラジオボタンの表示変更が必要かが分かり, 自身で notify を発行することが出来るのではないでしょうか.
jun74

2019/10/10 13:42

いつもありがとうございます。 アダプタで再生、停止が基本なのですが、Activity(現状はFragmentに変わりました)からも停止するタイミングがあり、そこの解消方法(static以外での呼び出し)が浮かびません。。
jimbe

2019/10/10 14:43

SoundAdapter の2つのインスタンスをそれぞれ AlarmFragment 上のRecyclerView と MusicFragment 上の RecyclerView にアダプタとして設定しているために プレイヤー関係を static にしているものと推測しています. であれば, プレイヤー関係を統括するクラスを新たに作ってインスタンスを1つ用意し, それを各 SoundAdapter や Fragment? から使用すればよいかと思います.
jun74

2019/10/10 15:05

ありがとうございます! SoundAdapterでプレイヤー制御しているのですが、AlarmFragmentやMusicFragmentが非表示になった瞬間にプレイヤーを停止したくてstaticにしています。 プレイヤーを統括するクラスを作ってインスタンスを用意して使用するようにしてみようと思います。 https://www.sejuku.net/blog/50043 上記より、aというインスタンスにplayというメソッド、stopというメソッドを作り、SoundAdapterで再生、AlarmFragmentで停止と出来るなら良さげです。 明日にでも試してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問