Kỹ thuật hiển thị danh sách phát nhạc sử dụng ListView trên Android

Để hiển thị danh sách dữ liệu dạng cuộn trên Android, ListView là một thành phần giao diện phổ biến. Tuy nhiên, việc sử dụng控件 này đòi hỏi phải kết hợp chặt chẽ với Adapter để ánh xạ dữ liệu vào từng mục con. Dưới đây là quy trình triển khai cụ thể để xây dựng một danh sách phát nhạc từ hệ thống.

Đầu tiên, cần khai báo thành phần ListView trong file layout chính. Đoạn mã XML dưới đây định nghĩa một vùng hiển thị chiếm toàn bộ chiều ngang và co giãn theo chiều dọc:

<ListView
    android:id="@+id/musicListView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Mỗi phần tử trong danh sách cần một layout riêng để định dạng thông tin hiển thị. File layout này (ví dụ: item_audio_track.xml) sẽ chứa các thành phần như TextView để hiển thị tiêu đề và tên nghệ sĩ:

<LinearLayout
    android:layout_width="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="wrap_content"
    android:id="@+id/trackContainer"
    android:paddingBottom="5dp" >

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/trackTitle"
        android:textSize="28sp">
    </TextView>

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/trackArtist">
    </TextView>
</LinearLayout>

Dữ liệu nhạc thường được lưu trữ trong cơ sở dữ liệu hệ thống thông qua MediaStore.Audio.Media. Để tiện quản lý, nên đóng gói thông tin này vào một lớp đối tượng riêng. Lớp AudioTrack dưới đây lưu trữ các thuộc tính cần thiết như ID, tiêu đề, kích thước và đường dẫn:

public class AudioTrack {

    private String trackId;
    private String title;
    private String fileSize;
    private String artistName;
    private long duration;
    private String filePath;

    public AudioTrack() {
        super();
    }

    public AudioTrack(String id, String title, String size, String artist) {
        super();
        this.trackId = id;
        this.title = title;
        this.fileSize = size;
        this.artistName = artist;
    }

    public String getTrackId() {
        return trackId;
    }

    public void setTrackId(String id) {
        this.trackId = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtistName() {
        return artistName;
    }

    public void setArtistName(String artist) {
        this.artistName = artist;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public String getFileSize() {
        return fileSize;
    }

    public void setFileSize(String size) {
        this.fileSize = size;
    }

    public void setFileSize(long size) {
        this.fileSize = String.valueOf(size);
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String path) {
        this.filePath = path;
    }
}

Tiếp theo là phương thức truy vấn dữ liệu từ hệ thống. Hàm này sẽ quét toàn bộ file âm thanh và chuyển đổi vào danh sách đối tượng AudioTrack:

public static List<AudioTrack> queryAudioTracks(Context context) {
    Cursor cursor = context.getContentResolver().query(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        null,
        null,
        null,
        MediaStore.Audio.Media.DEFAULT_SORT_ORDER
    );

    List<AudioTrack> trackList = new ArrayList<>();
    if (cursor != null) {
        while (cursor.moveToNext()) {
            long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
            String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
            String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
            long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
            long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));
            String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
            int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));

            if (isMusic != 0) {
                AudioTrack track = new AudioTrack();
                track.setTrackId(String.valueOf(id));
                track.setTitle(title);
                track.setArtistName(artist);
                track.setDuration(duration);
                track.setFileSize(size);
                track.setFilePath(path);
                trackList.add(track);
            }
        }
        cursor.close();
    }
    return trackList;
}

Sau khi có dữ liệu, cần liên kết với ListView thông qua Adapter. Biến điều khiển và quá trình khởi tạo được thực hiện như sau:

private ListView listViewContainer;
List<AudioTrack> audioDataList;

listViewContainer = findViewById(R.id.musicListView);

Để hiển thị dữ liệu, sử dụng SimpleAdapter để ánh xạ từ danh sách dữ liệu sang layout của từng mục. Lưu ý rằng việc khởi tạo Adapter nên được thực hiện sau khi đã hoàn tất việc thu thập dữ liệu để tối ưu hiệu suất:

ArrayList<HashMap<String, String>> displayList = new ArrayList<>();
audioDataList = queryAudioTracks(getApplicationContext());

for (AudioTrack track : audioDataList) {
    HashMap<String, String> itemMap = new HashMap<>();
    itemMap.put("trackTitle", track.getTitle());
    itemMap.put("trackArtist", track.getArtistName());
    displayList.add(itemMap);
}

SimpleAdapter trackAdapter = new SimpleAdapter(
    this,
    displayList,
    R.layout.item_audio_track,
    new String[] {"trackTitle", "trackArtist"},
    new int[] {R.id.trackTitle, R.id.trackArtist}
);

listViewContainer.setAdapter(trackAdapter);

Để xử lý sự kiện người dùng chọn một bài hát, cần thiết lập OnItemClickListener. Khi một mục được nhấn, ứng dụng sẽ chuyển sang giao diện phát nhạc và khởi chạy service nền:

listViewContainer.setOnItemClickListener(new TrackSelectionHandler());

private class TrackSelectionHandler implements AdapterView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (audioDataList != null && position < audioDataList.size()) {
            Intent playIntent = new Intent();
            playIntent.setClass(MainActivity.this, PlayingActivity.class);
            startActivity(playIntent);

            final int selectedIndex = position;
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    AudioTrack selectedTrack = audioDataList.get(selectedIndex);
                    Intent serviceIntent = new Intent();
                    serviceIntent.putExtra("filePath", selectedTrack.getFilePath());
                    serviceIntent.putExtra("listIndex", selectedIndex);
                    serviceIntent.putExtra("command", AppConstant.PlayerMsg.PLAY_MSG.ordinal());
                    serviceIntent.setClass(MainActivity.this, PlayerService.class);
                    startService(serviceIntent);
                }
            }, 300);
        }
    }
}

Thẻ: Android ListView Adapter mediastore Java

Đăng vào ngày 30 tháng 6 lúc 13:57