使用位图减少ListView中的内存消耗

时间:2015-01-09 17:35:11

标签: android listview android-fragments bitmap

我正在使用此片段,其中相应歌曲的歌曲标题,艺术家姓名和专辑封面正在自定义ListView中显示。

我正在顺利滚动代码。但问题是只包含一个Activity和Fragment的应用程序的内存消耗非常高。你能建议替代方法吗?或者帮我提高这段代码的效率。感谢。

package com.vamp.playerFragments;

import android.content.ContentUris;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.vamp.R;
import com.vamp.adapters.AllSongsAdapter;
import com.vamp.models.AllSongsModel;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class AllSongs extends Fragment {
public AllSongsAdapter adapter;
private ListView allSongsList;
private int[] albumArts;
private String[] allSongs;
private String[] artistName;
private ArrayList<AllSongsModel> rowItems;
private OnFragmentInteractionListener mListener;

public AllSongs() {
    // Required empty public constructor
}
public static AllSongs newInstance(String param1, String param2) {
    AllSongs fragment = new AllSongs();
    Bundle args = new Bundle();
    return fragment;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_all_songs, container, false);
    allSongsList = (ListView) rootView.findViewById(R.id.allSongsList);
    rowItems = new ArrayList<AllSongsModel>();
    init_Songs_list();
    adapter = new AllSongsAdapter(getActivity(), rowItems);
    allSongsList.setAdapter(adapter);
    return rootView;
}

public void init_Songs_list() {
    Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    String proj[] = {
            MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM_ID
    };

    Cursor MainCursor = getActivity().getContentResolver().query(uri, proj, MediaStore.Audio.Media.IS_MUSIC + " =1", null, MediaStore.Audio.Media.TITLE + " ASC");
    MainCursor.moveToFirst();
    while (MainCursor.moveToNext()) {

        String title = MainCursor.getString(MainCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
        String artistName = MainCursor.getString(MainCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
        Long albumId = MainCursor.getLong(MainCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
        Uri sArtWorkUri = Uri.parse("content://media/external/audio/albumart");
        Uri albumArtUri = ContentUris.withAppendedId(sArtWorkUri, albumId);

        Bitmap bitmap = null;
        try {
            bitmap = MediaStore.Images.Media.getBitmap(
                    getActivity().getContentResolver(), albumArtUri);
            //bitmap = Bitmap.createScaledBitmap(bitmap, 30, 30, true);

        } catch (FileNotFoundException exception) {
            exception.printStackTrace();
            bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
                    R.drawable.ic_launcher);
        } catch (IOException e) {

            e.printStackTrace();
        }
        AllSongsModel allSongsModel = new AllSongsModel();
        allSongsModel.setSongName(title);
        allSongsModel.setArtistName(artistName);
        allSongsModel.setAlbumArt(bitmap);
        rowItems.add(allSongsModel);
    }

}

}

3 个答案:

答案 0 :(得分:0)

我不知道您是否喜欢使用第三方库,但我在我的项目中使用了这个,并且针对这种情况进行了优化(还有很多其他的)。检查Picasso,试一试!它非常易于使用,而且他们的文档非常出色。

希望它有所帮助!

答案 1 :(得分:0)

您应该在使用以下代码加载位图之前调整位图大小:

Bitmap downsizeBitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);

如果您的位图要大得多,这将大大减少内存消耗。

答案 2 :(得分:0)

在搜索并实现了很多方法后,我找到了这个很棒的库。 https://github.com/nostra13/Android-Universal-Image-Loader并根据说明实施,现在该应用程序正常运行。没有更多的内存问题和几乎相同的性能。看看下面的代码。

package com.vamp.adapters;
import...//all the imports/

public class AllSongsAdapter extends BaseAdapter {
private ArrayList<AllSongsModel> mAllSongsList;
private Context context;
private LayoutInflater mInflater;
private AllSongsModel allSongsModel;
private Bitmap bmp;
public AllSongs allSongs;

//Android Universal Image Loader Classes.
private DisplayImageOptions options;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();

public AllSongsAdapter(Context context, ArrayList<AllSongsModel> mAllSongsList) {
    mInflater = LayoutInflater.from(context);
    this.mAllSongsList = mAllSongsList;
    this.context = context;


    options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.ic_launcher)
            .showImageForEmptyUri(R.drawable.ic_launcher)
            .showImageOnFail(R.drawable.ic_launcher)
            .cacheInMemory(true)
            .cacheOnDisk(true)
            .considerExifParams(true)
            .displayer(new RoundedBitmapDisplayer(20))
            .build();
}

@Override
public int getCount() {
    return mAllSongsList.size();
}

@Override
public Object getItem(int position) {
    return mAllSongsList.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View view;
    ViewHolder holder;
    if (convertView == null) {
        view = mInflater.inflate(R.layout.all_songs_list_row, parent, false);
        holder = new ViewHolder();
        holder.albumArt = (ImageView) view.findViewById(R.id.all_songs_list_row_albumart);
        holder.songName = (TextView) view.findViewById(R.id.all_songs_list_row_songName);
        holder.artistName = (TextView) view.findViewById(R.id.all_songs_list_row_artistName);
        view.setTag(holder);
    } else {
        view = convertView;
        holder = (ViewHolder) view.getTag();
        //holder.mImageLoader.cancel();
    }


    AllSongsModel allSongsModel = mAllSongsList.get(position);
   ImageLoader.getInstance().displayImage(Uri.decode(String.valueOf(allSongsModel.getAlbum_art_uri())),holder.albumArt,options,animateFirstListener);
    holder.songName.setText(allSongsModel.getSongName());
    holder.artistName.setText(allSongsModel.getArtistName());
    return view;
}

private class ViewHolder {
    public ImageView albumArt;
    public TextView songName, artistName;
    public AsyncImageSetter mImageLoader;
}

private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {

    static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());

    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
        if (loadedImage != null) {
            ImageView imageView = (ImageView) view;
            boolean firstDisplay = !displayedImages.contains(imageUri);
            if (firstDisplay) {
                FadeInBitmapDisplayer.animate(imageView, 500);
                displayedImages.add(imageUri);
            }
        }
    }
}
}

我的AllSongs.java(Fragment)类与以前相同,只有一个更改而不是直接使用Bitmap适配器我现在将该位图的URI传递给adpater.And应用程序完美无瑕。

感谢所有向我提出不同解决方案方法的人。我从中学到了很多东西。