java - 更新 fragment 中的ListView

标签 java android listview android-fragments

我在 fragment A 中有一个上下文菜单,其中包含 DialogFragment。在 DialogFragment 的帮助下,我创建了一个保存在 MediaStore.Playlists 中的播放列表。在 fragment B 中,我显示了一个带有播放列表的 ListView

当我添加新的播放列表时,如何更新 fragment B 中的 Listview

P.S 我正在尝试在我的适配器上使用notifydatasetchanged()`,但它不起作用。

这是我无法更新的 PlaylistFragment:

private ListView lvPlaylists;
private int[] images = new int[] { R.drawable.icon_playlist };
private ArrayList<HashMap<String, String>> listPlaylists = new ArrayList<HashMap<String, String>>();;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View v = inflater.inflate(R.layout.playlists, null);

    listPlaylists = getAllPlaylists(getActivity());

    lvPlaylists = (ListView) v.findViewById(R.id.lvPlaylists);

    List<Map<String, String>> data = new ArrayList<Map<String, String>>();

    for (int i = 0; i < listPlaylists.size(); i++) {
        Map<String, String> datum = new HashMap<String, String>(2);
        datum.put("elementPlaylist",
                listPlaylists.get(i).get("playlistName"));
        datum.put("imagesPlaylist", Integer.toString(images[0]));
        data.add(datum);
    }

    SimpleAdapter sAdapter = new SimpleAdapter(getActivity(), data,
            R.layout.list_playlist_element, new String[] {
                    "elementPlaylist", "imagesPlaylist" }, new int[] {
                    R.id.tvName, R.id.ivIcon });

    lvPlaylists.setAdapter(sAdapter);
    lvPlaylists.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
            String playlistId = listPlaylists.get(pos).get("playlistId");

            Intent playlistSongs = new Intent(getActivity(),
                    PlaylistSongs.class);
            playlistSongs.putExtra("playlistId", playlistId);
            startActivity(playlistSongs);
        }
    });

    return v;

}

public ArrayList<HashMap<String, String>> getAllPlaylists(Context context) {
    String[] projection = { MediaStore.Audio.Playlists._ID, // 0
            MediaStore.Audio.Playlists.NAME // 1
    };

    Cursor playListSDCardCursor = myquery(context,
            MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, projection,
            null, null, MediaStore.Audio.Playlists.NAME, 0);

    if (playListSDCardCursor.moveToFirst()) {
        for (int i = 0; i < playListSDCardCursor.getCount(); i++) {
            HashMap<String, String> playlist = new HashMap<String, String>();
            playlist.put(
                    "playlistName",
                    playListSDCardCursor.getString(playListSDCardCursor
                            .getColumnIndex(MediaStore.Audio.Playlists.NAME)));
            playlist.put(
                    "playlistId",
                    playListSDCardCursor.getString(playListSDCardCursor
                            .getColumnIndex(MediaStore.Audio.Playlists._ID)));
            listPlaylists.add(playlist);

            playListSDCardCursor.moveToNext();
        }
    }
    playListSDCardCursor.close();
    return listPlaylists;

}

public static Cursor myquery(Context context, Uri uri, String[] projection,
        String selection, String[] selectionArgs, String sortOrder,
        int limit) {
    try {
        ContentResolver resolver = context.getContentResolver();
        if (resolver == null) {
            return null;
        }
        if (limit > 0) {
            uri = uri.buildUpon().appendQueryParameter("limit", "" + limit)
                    .build();
        }
        return resolver.query(uri, projection, selection, selectionArgs,
                sortOrder);
    } catch (UnsupportedOperationException ex) {
        return null;
    }
}

这是 DialogFragment,我在其中创建新的播放列表:

public class MyDialogFragment extends DialogFragment {
    Context mContext;

    public MyDialogFragment() {

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("Введите имя плейлиста:");

        final EditText input = new EditText(getActivity());
        input.setId(0);
        builder.setView(input);

        builder.setPositiveButton("Ок", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int whichButton) {
                String value = input.getText().toString();
                Log.d("", "User name: " + value);
                if (value != null) {
                    ContentValues cv = new ContentValues();
                    cv.put(MediaStore.Audio.Playlists.NAME, value);
                    Uri uri = getActivity().getContentResolver().insert(
                            MediaStore.Audio.Playlists
                                    .getContentUri("external"), cv);
                }

                return;
            }
        });

        builder.setNegativeButton("Отмена",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
        return builder.create();
    }
}

这是 TrackFragment,我在其中调用上下文菜单并显示 FragmentDialog:

public class TrackFragment extends Fragment {

    private ListView lvTracks;
    private static ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
    private int songIndex;
    private Utilities utils;

    private ArrayList<HashMap<String, String>> listPlaylists = new ArrayList<HashMap<String, String>>();;
    private int countPlaylist = 0;

    private int itemPosition;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.track, null);

        utils = new Utilities();

        songsList = getAllSongs(getActivity());

        List<Map<String, String>> data = new ArrayList<Map<String, String>>();
        for (int i = 0; i < songsList.size(); i++) {
            Map<String, String> datum = new HashMap<String, String>(2);
            datum.put("songTitle", songsList.get(i).get("songTitle"));
            datum.put("songArtist", songsList.get(i).get("songArtist"));
            datum.put("songDuration", songsList.get(i).get("songDuration"));
            datum.put("songAlbum", songsList.get(i).get("songAlbum"));
            data.add(datum);
        }

        lvTracks = (ListView) v.findViewById(R.id.lvTracks);
        lvTracks.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                songIndex = position;
                writeData();

                Intent mainIntent = new Intent(getActivity().getBaseContext(),
                        PlayerActivity.class);

                mainIntent.putExtra("songIndex", position);
                Bundle b = new Bundle();
                b.putInt("songIndex", position);
                b.putInt("mediaIndex",
                        Integer.parseInt(songsList.get(position).get("songId")));

                mainIntent.putExtras(b);
                int albumId = Integer.parseInt(songsList.get(position).get(
                        "songAlbum"));
                Bitmap cover = utils.getAlbumart(albumId, getActivity()
                        .getApplicationContext());
                if (cover == null) {
                    cover = BitmapFactory.decodeResource(getResources(),
                            R.drawable.nocover);
                }

                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                cover.compress(Bitmap.CompressFormat.PNG, 100, stream);

                byte[] byteArray = stream.toByteArray();
                mainIntent.putExtra("albumArt", byteArray);

                mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mainIntent);
            }
        });

        registerForContextMenu(lvTracks);

        SimpleAdapter sAdapter = new SimpleAdapter(getActivity(), data,
                R.layout.list_track_element, new String[] { "songTitle",
                        "songArtist", "songDuration" },
                new int[] { R.id.tvSongName, R.id.tvSongArtist,
                        R.id.tvSongDuration });
        lvTracks.setAdapter(sAdapter);
        return v;
    }

    public void onCreateContextMenu(android.view.ContextMenu menu, View v,
            android.view.ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        countPlaylist++;

        if (countPlaylist > 1) {
            listPlaylists.clear();
            listPlaylists = getAllPlaylists(getActivity()
                    .getApplicationContext());
        } else {
            listPlaylists = getAllPlaylists(getActivity()
                    .getApplicationContext());
        }
        menu.setHeaderIcon(R.drawable.ic_launcher);

        menu.setHeaderTitle("Добавить в плейлист");
        menu.add(0, 0, 0, "Новый плейлист");

        for (int i = 0; i < listPlaylists.size(); i++)
            menu.add(0, i + 1, 0, listPlaylists.get(i).get("playlistName"));
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
                .getMenuInfo();
        itemPosition = info.position;

        if (item.getItemId() == 0) {
            createPlaylist(item.getItemId());
        }

        else {
            Log.d("Playlist id",
                    Integer.parseInt(listPlaylists.get(item.getItemId()).get(
                            "playlistId"))
                            + "");
            addToPlaylist(Integer.valueOf(listPlaylists.get(
                    item.getItemId() - 1).get("playlistId")));
        }
        return true;
    }

    private void createPlaylist(int itemId) {
        new MyDialogFragment().show(getFragmentManager(), "MyDialog");
    }

    private void addToPlaylist(int playlistId) {
        ContentResolver resolver = getActivity().getContentResolver();
        String[] cols = new String[] { "count(*)" };
        Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external",
                playlistId);
        Cursor cur = resolver.query(uri, cols, null, null, null);
        cur.moveToFirst();
        final int base = cur.getInt(0);
        cur.close();
        ContentValues values = new ContentValues();
        values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER,
                Integer.valueOf(base + 1));

        values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID,
                Integer.valueOf(songsList.get(itemPosition).get("songId")));
        Log.d("mediaIndex", songsList.get(itemPosition).get("songId") + "");

        resolver.insert(uri, values);
    }

    public ArrayList<HashMap<String, String>> getAllPlaylists(Context context) {
        String[] projection = { MediaStore.Audio.Playlists._ID,
                MediaStore.Audio.Playlists.NAME };

        Cursor playListSDCardCursor = myquery(context,
                MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, projection,
                null, null, MediaStore.Audio.Playlists.NAME, 0);

        if (playListSDCardCursor.moveToFirst()) {
            for (int i = 0; i < playListSDCardCursor.getCount(); i++) {
                HashMap<String, String> playlist = new HashMap<String, String>();
                playlist.put(
                        "playlistName",
                        playListSDCardCursor.getString(playListSDCardCursor
                                .getColumnIndex(MediaStore.Audio.Playlists.NAME)));
                playlist.put(
                        "playlistId",
                        playListSDCardCursor.getString(playListSDCardCursor
                                .getColumnIndex(MediaStore.Audio.Playlists._ID)));
                listPlaylists.add(playlist);

                playListSDCardCursor.moveToNext();
            }
        }
        playListSDCardCursor.close();
        return listPlaylists;
    }
}

我已经部分解决了手动添加播放列表的问题:

Map<String, String> datum = new HashMap<String, String>(2);
datum.put("elementPlaylist", value);
datum.put("imagesPlaylist", Integer.toString(images[0]));

PlaylistFragment.data.add(datum);

并在 ListView 中添加播放列表,但单击它会抛出:

java.lang.IndexOutOfBoundsException: Invalid index 18, size is 18

最佳答案

使用 CursorLoader 填充列表 fragment http://developer.android.com/reference/android/content/CursorLoader.html

它会将通知 uri 设置为您的 Cursor sp,它将自动更新

使您的 fragment 实现 LoaderCallbacks

class PlaylistFragment extends Fragment implements LoaderCallbacks<Cursor>{

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    sAdapter.swapCursor(null);
}


@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new CursorLoader(getActivity(), MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, projection, null, null, null)
}

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor result) {
    sAdapter.swapCursor(result);
}

@Override
public void onStart(){
getLoaderManager().restartLoader(0, null, this);
}


}

仅此而已,加载程序将自动要求更改播放列表

关于java - 更新 fragment 中的ListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17024219/

相关文章:

android ksoap调用xmlpullparser异常

android在ImageView中共享图像而不保存在sd卡中

android - 如何在android中制作自定义搜索栏?

c - 在 Win32 的 ListView 中保持行永久选中

c# - 检查数据行中是否存在具有给定名称的列

java - 尽管存在 “FATAL: database ',但出现错误 'db name' 数据库名称“不存在”

java - 多态性和基于实例的switch case

java - Spring-Core-WS 与 Spring 4.3.0 不兼容,是吗?

java - 进度条适用于 Android API 23,但不适用于 21 或 22

c# - 从 SQL 数据库动态分配行颜色到 ListView WPF