【问题标题】:Video Gallery is not scrolling smooth视频库滚动不流畅
【发布时间】:2018-01-18 19:34:04
【问题描述】:

我正在使用网格视图,它从布局中扩展 custom_layout。网格视图正在从手机加载视频并以缩略图的形式填充它。一切正常。滚动网格视图时出现问题。它滚动缓慢,并且在 API > 20 的手机中发出消息 应用没有响应

我已经关注了这个链接,但没有找到完美的解决方案: Gridview is scrolling slow

我使用异步任务从图库中加载视频。我正在给出相同的代码。这是我的片段:

1. AddFragment.java

public class AddFragment extends Fragment {

private ImageButton imageButton;
private GridView gridView;
private ProgressDialog videoProgressDialog;
ArrayList<File> list = new ArrayList<>();
ImageAdapter imageAdapter;

public AddFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_add, container, false);

    imageButton = (ImageButton) view.findViewById(R.id.gotoButton);

    gridView = (GridView) view.findViewById(R.id.grid_view);
    gridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    Log.e("ADD_VIDEOS","FRAGMENT CREATED");
    videoProgressDialog = new ProgressDialog(getContext());
    videoProgressDialog.setTitle("Loading Videos");
    videoProgressDialog.setMessage("please wait.....");
    videoProgressDialog.setCancelable(false);
    videoProgressDialog.show();

    LoadVideoTask videoTask = new LoadVideoTask();
    videoTask.execute(new File("/mnt"));

    return view;
}

//reading the file from the storage
void videoReader(File root) {


    File[] file = root.listFiles();

    if (file != null) {

        for (File aFile : file) {
            if (!aFile.isDirectory()) {
                if (aFile.getName().endsWith(".mp4")) {
                    Log.e("VIDEO_FILE=====", aFile.getName());
                    list.add(aFile);
                }
            } else
                videoReader(aFile);
        }
    } else{}
}

//Show hide select button if images are selected or deselected
public void showSelectButton() {
    ArrayList<String> selectedItems = imageAdapter.getCheckedItems();
    Log.e("CHECKED_ITEMS",imageAdapter.getCheckedItems().toString());
    if (selectedItems.size() > 0) {
        imageButton.setVisibility(View.VISIBLE);
    } else
        imageButton.setVisibility(View.GONE);

}

 class ImageAdapter extends BaseAdapter {


    private Bitmap bitmap;

    private LayoutInflater inflater;
     SparseBooleanArray mSparseBooleanArray;

    private final Context context;

    private ImageAdapter(Context c) {
        context = c;
        //changes done from here
        mSparseBooleanArray = new SparseBooleanArray();

    }

    //Method to return selected Images
    public ArrayList<String> getCheckedItems() {
        ArrayList<String> mTempArry = new ArrayList<String>();

        for (int i = 0; i < list.size(); i++) {
            if (mSparseBooleanArray.get(i)) {
                mTempArry.add(list.get(i).toString());
            }
        }

        return mTempArry;
    }


    //for the video numbers
    @Override
    public int getCount() {
        return list.size();
    }

    //for getting the video items position vise
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

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


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

        View v;

        if (convertView == null) {

            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.custom_gridview,viewGroup,false);
            v.setLayoutParams(new AbsListView.LayoutParams(215,215));

        } else {
           // picturesView = (ImageView) convertView;
            v = (View)convertView;
        }

        Viewholder viewHolder = new Viewholder(v);
        //viewHolder.imageView.setId(position);
        viewHolder.id = position;
        //convertView.setTag(viewHolder);

        //loading images from the videos
        if (list.get(position).toString().contains(".jpg")) {
            bitmap = BitmapFactory.decodeFile(list.get(position).toString()); //Creation of Thumbnail of image
          //  viewHolder.imageView.setImageBitmap(bitmap);
        } else {
            if (list.get(position).toString().contains(".mp4")) {
                bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
                viewHolder.imageView.setImageBitmap(bitmap);
            }
        }

        //picturesView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        //picturesView.setAdjustViewBounds(true);
        //picturesView.setLayoutParams(new GridView.LayoutParams(215, 215));
        //picturesView.setImageBitmap(bitmap);
        //setting layout params for every device

        viewHolder.checkBox.setTag(position);
        viewHolder.checkBox.setChecked(mSparseBooleanArray.get(position));
        CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                mSparseBooleanArray.put((Integer) compoundButton.getTag(), isChecked);//Insert selected checkbox value inside boolean array
                showSelectButton();
            }
        };
        viewHolder.checkBox.setOnCheckedChangeListener(mCheckedChangeListener);


        //return picturesView;
        return v;

    }

     class Viewholder {
        public ImageView imageView;
        public CheckBox checkBox;
         public int id;
         public Viewholder(View v){
             imageView = (ImageView) v.findViewById(R.id.galleryImageView);
             checkBox = (CheckBox) v.findViewById(R.id.selectCheckBox);
         }
    }
}

//asynch task has been done to do the processing in the background for loading the videos
//three parametres are Params,Progress,Result
private class LoadVideoTask extends AsyncTask<File,Integer, Integer>{


    @Override
    protected Integer doInBackground(File... files) {
        for(int i=0;i<files.length;i++) {
            videoReader(files[i]);
            Log.e("VIDEO_LOAD", files[i].toString());
        }
        return files.length;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        videoProgressDialog.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);
        updateUI();
    }
}

private void updateUI() {

    videoProgressDialog.dismiss();
    //calling imageadapter class in here
    imageAdapter = new ImageAdapter(getContext());
    //for not repeating of the files
    LinkedHashSet<File> fileList = new LinkedHashSet<>();
    fileList.addAll(list);
    list.clear();
    list.addAll(fileList);
    gridView.setAdapter(imageAdapter);

    imageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getContext(), EditVideoActivity.class);
            intent.putExtra("sendData", imageAdapter.getCheckedItems());   //passing the data
            Log.e("SEND_DATA", imageAdapter.getCheckedItems().toString());
            startActivity(intent);
        }
    });
}}

因为有很多数据,而且我知道由于数据量大,所以滚动速度并不慢。我需要一个解决方案。提前致谢。

编辑

点击此链接后,我得到了结果,并根据解决方案在 getView() 中进行了一些更改,但仍然没有解决我的问题。

链接:GridView Smooth Scrolling Solution

我的 getView() 现在是这样的:

我的 Adapter 类中的 getView() 方法

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


        Viewholder viewHolder = null;

        if (convertView == null) {

            viewHolder = new Viewholder();

            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.custom_gridview,viewGroup,false);
            convertView.setLayoutParams(new AbsListView.LayoutParams(215,215));

            convertView.setTag(viewHolder);

        } else {
            viewHolder = (Viewholder) convertView.getTag();
        }

        viewHolder.imageView = (ImageView) convertView.findViewById(R.id.galleryImageView);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.selectCheckBox);
        viewHolder.id = position;

        //loading images from the videos
        if (list.get(position).toString().contains(".jpg")) {
            bitmap = BitmapFactory.decodeFile(list.get(position).toString()); //Creation of Thumbnail of image
          //  viewHolder.imageView.setImageBitmap(bitmap);
        } else {
            if (list.get(position).toString().contains(".mp4")) {
                bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
                viewHolder.imageView.setImageBitmap(bitmap);
            }
        }

        viewHolder.checkBox.setTag(position);
        viewHolder.checkBox.setChecked(mSparseBooleanArray.get(position));
        CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                mSparseBooleanArray.put((Integer) compoundButton.getTag(), isChecked);//Insert selected checkbox value inside boolean array
                showSelectButton();
            }
        };
        viewHolder.checkBox.setOnCheckedChangeListener(mCheckedChangeListener);

        return convertView;

    }

【问题讨论】:

  • 查看此链接:developer.android.com/training/improving-layouts/…。或者尝试使用 RecycleView
  • 图像正在加载.. asynch 任务执行此操作。但是加载图像后它滚动很慢
  • 是图像处理导致缓慢吗?每次调用 getView() 时,您都在解码位图或从 .mp4 创建缩略图。这需要一些时间。这可以在后台线程上提前完成吗?可能是 AsyncTask 的一部分?
  • 没有真正的问题在于大量数据。图像已成功填充,一切正常。但是当所有数据都出现时,现在如果要滚动它滚动速度很慢。是的,如果视频较少,问题就不存在了。 我相信你可能明白我想说的话

标签: android gridview vertical-scrolling video-gallery


【解决方案1】:

位图很容易耗尽应用程序的内存预算。

如果您的应用正在将多个位图加载到内存中,您需要巧妙地管理内存和磁盘缓存。 因此,每当您从视频中加载图像时,一定会耗尽应用程序的内存预算。

我推荐使用毕加索图书馆。(http://square.github.io/picasso/)

Picasso.with(context).load(new File(YOUR_FILE_PATH)).into(imageView);

你必须在你的源代码中改变它。

if (list.get(position).toString().contains(".mp4")) {
            bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
            Picasso.with(context).load(getImageUri(context, bitmap)).into(viewHolder.imageView);}

public Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

请仔细阅读

solving-the-android-image-loading-problem-volley-vs-picasso/

Handling Bitmaps

【讨论】:

  • 我会试着告诉你结果
  • 我已经这样做了,但有一些变化,比如 new File(list.get(position).toString()) 是的,into 没有被解析,因为它显示了无法解析为(android.widget.imageView) 以及另一件事,位图将在哪里使用?
  • 我已经按照您的建议进行了操作,但这使事情变得更加复杂,在此之前,所有图像都同时填充,但滚动速度很慢。现在问题增加了,当我滚动时,图像只显示在这个时间,并且滚动也因此太慢。这不是我现在正在寻找的解决方案。
  • 请上传您的完整源码,例如github
  • 很抱歉,我不能,我不允许这样做。这是我面临问题的代码。您只需要查看代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 2014-12-06
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多