1

リサイクルアダプターを使用してデバイス上の曲のリストをSong Fragmentから取得したいとします。曲のリストを取得するために実装されたコンテンツリゾルバがエラーになります。 助けてくださいandroidのフラグメントでリサイクラーアダプターを使用しているデバイスから曲のリストを取得する方法

これは私がやったことです。

  • 私は
  • 拡張3つの断片ソングモデルを作成した(以下ソング断片の一つである)主な活動から

マイSongFragment

public class TabSong extends Fragment { 
RecyclerView recyclerView; 
RecyclerAdapter adapter; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Get the view from fragmenttab1.xml 
    View v = inflater.inflate(R.layout.tab_song, container, false); 
    recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view); 

    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); 
    recyclerView.setLayoutManager(mLayoutManager); 

    adapter = new RecyclerAdapter(); 
    SongList(); 
    recyclerView.setAdapter(adapter); 

    return v; 
} 

public void SongList() { 
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0"; 
    String sortOrder = MediaStore.Audio.Media.TITLE + " ASC"; 

    ContentResolver cr = getActivity().getContentResolver(); 
    String[] projection = { 
      MediaStore.Audio.Media._ID, 
      MediaStore.Audio.Media.ARTIST, 
      MediaStore.Audio.Media.TITLE, 
      MediaStore.Audio.Media.DATA, 
      MediaStore.Audio.Media.DISPLAY_NAME, 
      MediaStore.Audio.Media.DURATION 
    }; 

    Cursor cur = cr.query(
      MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 
      projection, 
      selection, 
      null, 
      sortOrder); 

    RecyclerAdapter.songs = new ArrayList<>(); 
    while (cur.moveToNext()) { 
     HashMap<String, String> map = new HashMap<>(); 
    /* songs.add(cur.getString(0) + "||" 
      + cur.getString(1) + "||" 
      + cur.getString(2) + "||" 
      + cur.getString(3) + "||" 
      + cur.getString(4) + "||");*/ 

     map.put("ID", cur.getString(0)); 
     map.put("artist", cur.getString(1)); 
     map.put("title", cur.getString(2)); 
     map.put("displayname", cur.getString(3)); 
     map.put("duration", cur.getString(4)); 

     RecyclerAdapter.songs.add(map); 
    } 
}} 

マイRecyclerAdapter

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>{ 

static ArrayList<HashMap<String, String>> songs = new ArrayList<>(); 

@Override 
public RecyclerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.song_list, parent, false); 
    MyViewHolder holder = new MyViewHolder(view); 
    return holder; 
} 

@Override 
public void onBindViewHolder(MyViewHolder holder, int position) { 
    holder.title.setText(songs.get(position).get("displayname")); 
    holder.artist.setText(songs.get(position).get("artist")); 
    holder.duration.setText(songs.get(position).get("duration")); 
} 

@Override 
public int getItemCount() { 
    return songs.size(); 
} 

public class MyViewHolder extends RecyclerView.ViewHolder{ 
    public TextView title,duration,artist; 

    public MyViewHolder(View view) { 
     super(view); 
     title = (TextView) view.findViewById(R.id.list_title); 
     artist = (TextView) view.findViewById(R.id.list_artist); 
     duration = (TextView) view.findViewById(R.id.list_duration); 
    } 
}} 

答えて

1

#1:静的メンバーを使用して、アダプタに曲を保存しないでください。必要なのは、すべての曲データを保持するために定義できるクラスのListです。

public class Song { 
    String displayName; 
    String artist; 
    // etc. 
} 

は、それがロードされるたびに新しいListにスワップするために、あなたのアダプタでメソッドを作成します。それについて...

#2:あなたはLoaderを使用して曲を読み込む必要があります。ローダーhereに関するガイドがあります。あなたが今やっているやり方は、UIスレッド上でMediaProviderに問い合わせを行い、その結果をUIスレッド上で処理することです。これは悪いことです。また、Loaderは、データが変更された場合に自動的にリロードできます。つまり、手動で更新する必要はありません。

onLoadFinished()のメインスレッドの結果を処理していても、基本的なCursorLoaderを使用して開始できます。これをよりうまく実行したい場合は、クエリーを実行して結果をすべてバックグラウンドで処理し、最終的なデータ構造を公開するカスタムLoaderを作成することができます。

また、完了したらCursorを閉じてください。

#3:あなたは、追加、削除、またはアダプタをバックアップする項目を変更した後RecyclerViewが更新されたデータを表示するように、あなたは(ドキュメントはhereを開始参照)アダプタのnotify...の方法のいずれかを呼び出す必要があります。

+0

ありがとう@カラクリ。 1重要な質問、簡単に説明できますか?どのようにしてonCreateメソッドだけが存在するメインアクティビティにすべて(SongFragment、Recyclerアダプタ、ローダ、モデル)を接続するのですか?また、上記のクラスのHashmap Arrayリストを宣言してインスタンス化する場所 – HSBP

+0

私は 'Hashmap'のリストを使用しません。とにかく 'Cursor'からデータを抽出する場合は、上記の' Song'モデルクラスの例のように直接アクセスできるものに抽出してください。あなたのアダプタはメソッド呼び出しで設定した 'List 'を持つことができます。アクティビティは 'RecyclerView'を取得し、アダプタを初期化し、' onCreate() 'でローダを起動する必要があります。 'initLoader()'に渡した 'LoaderCallbacks'の' onLoadFinished() 'にロードされたデータを取得します。そこでは、曲のリストに変換し、それをそのリストに置き換えて通知を行うアダプターに渡します。 – Karakuri

関連する問題