多个重复项从SD卡加载到GridView

时间:2015-04-28 00:21:53

标签: android android-asynctask android-mediaplayer android-gridview

我正在尝试将SD卡中的Uri声音文件加载到自定义GridView中,其中每个项目都包含ImageViewUri}和{{{} 1}}用于声音文件标题,但它不断加载重复项。我的卡上有6个声音文件,但它加载了12个,然后非常奇怪地在所有drawables加载后再加载3个。 drawables(占位符图像)加载正常,加载正确的数字。

我将大量文件I / O放入TextView,但我怀疑这会导致这样的问题。

当我记录所有内容时,我发现事情意外地被加载了几次(下面的控制台),包括奇数空值。我有其他工作代码完全相同的过程,除了加载图像而不是声音文件,它完美的工作,所以这真的很令人费解。我意识到将AsyncTask加载到Uri并不理想,因为GridView中没有任何内容可见,但是当我点击每个项目时,它会播放该文件,以便部分是正确的。我稍后会修改图像问题。

知道为什么事情在重复中如此奇怪地加载?感谢。

更新

事实证明,因为我的适配器构造函数中有ImageView,所以我的列表中的任何更改都会自动更新,因此我无需再次手动将其添加到适配器中。所以我刚刚在我的ArrayList<AudioGridItem>中删除了对适配器的添加,它确实有效!

onPostExecute()

enter image description here

AudioTab.java

@Override
        protected void onPostExecute(AudioGridItem result) {
            progressDialog.dismiss();

            // add the default icons remaining, to GridView, if less than 15 files on SD card
            for (int i = 0; i < (15 - numberSDCardFiles.length); i++) {
                audioAdapter.add(drawable);
            }

            audioAdapter.notifyDataSetChanged();

        }

GridViewAudioAdapter.java

package org.azurespot.cutecollection.audiotab;

import android.app.ProgressDialog;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;

import org.azurespot.R;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class AudioTab extends Fragment {

    private GridView gridView;
    private GridViewAudioAdapter audioAdapter;
    private ProgressDialog progressDialog;
    private String[] numberSDCardFiles = null;
    File[] files;
    ArrayList<AudioGridItem> audioFiles = new ArrayList<>();
    MediaPlayer mp;
    AudioGridItem audioGridItem;
    AudioGridItem drawable;

    public AudioTab(){
        super();
    }

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

        mp = new MediaPlayer();

        // instantiate your progress dialog
        progressDialog = new ProgressDialog(getActivity());

        // with fragments, make sure you include the rootView when finding id
        gridView = (GridView) v.findViewById(R.id.audio_grid);
        // Create the Custom Adapter Object
        audioAdapter = new GridViewAudioAdapter(getActivity(), audioFiles);
        // Set the Adapter to GridView
        gridView.setAdapter(audioAdapter);

        Log.d("TAG", "Items in audioAdapter1: " + audioAdapter.getCount());

        if(audioAdapter.getCount() == 0) {
            // load contents of SD card through AsyncTask
            new AudioDownloaderTask().execute();
        }

        setupGridViewListener();

        return v;
    }

    private class AudioDownloaderTask extends AsyncTask<Object, Void, AudioGridItem> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog.setMessage("Loading cute collection ...");
            //set the progress bar to cancelable on back button
            progressDialog.setCancelable(true);
            progressDialog.show();
        }

        @Override
        protected AudioGridItem doInBackground(Object... params) {

            retrieveAudio();

            return null;

        }

        @Override
        protected void onPostExecute(AudioGridItem result) {
            progressDialog.dismiss();

            Log.d("TAG", "Items in audioFiles: " + audioFiles.size());

            // Add whole ArrayList to adapter
            audioAdapter.addAll(audioFiles);

            Log.d("TAG", "Number of item in audioAdapter2: " + audioAdapter.getCount());

            // add the default icons remaining, to GridView, if less than 15 files on SD card
            for (int i = 0; i < (15 - numberSDCardFiles.length); i++) {
                audioAdapter.add(drawable);
            }

            audioAdapter.notifyDataSetChanged();
            Log.d("TAG", "Number of item in audioAdapter3: " + audioAdapter.getCount());
            Log.d("TAG", "Number of items in SD Card files: " +numberSDCardFiles.length);
        }
    }

    public void retrieveAudio() {

        try {
            // gets directory Cute Videos from sd card
            File cuteVideosDir = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_PODCASTS), "Cute Sounds");

            // puts list into files Array
            files = cuteVideosDir.listFiles();

            // get number of files in Cute Sounds directory
            numberSDCardFiles =  new String[files.length];

            for (File singleFile : files) {
                // get both audio file and audio title
                Uri audioUri = Uri.fromFile(singleFile);
                String audioTitle = singleFile.getName();

                audioGridItem = new AudioGridItem(audioUri, audioTitle);

                // add Uri and title to ArrayList
                audioFiles.add(audioGridItem);
            }

            // changes drawable into an AudioGridItem object (Uri, but no String)
            drawable = new AudioGridItem(Uri.parse("android.resource://org.azurespot/"
                                + R.drawable.ic_sounds_placeholder), null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setupGridViewListener() {
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView,
                                    View item, int pos, long id) {

                if(!(audioAdapter.getItem(pos).equals(drawable))) {

                    Uri soundFile = (audioAdapter.getItem(pos)).getAudio();

                    try {
                        mp.setDataSource(getActivity(), soundFile);
                        mp.prepare();
                        mp.start();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        });
    }
}

这是我的模型:AudioGridItem.java

package org.azurespot.cutecollection.audiotab;

import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.apache.commons.io.FilenameUtils;
import org.azurespot.R;

import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class GridViewAudioAdapter extends ArrayAdapter<AudioGridItem> {

    private TextView audioTitleView;
    int position;
    ViewHolder holder = null;

    public GridViewAudioAdapter(Context context, ArrayList<AudioGridItem> audio) {
        super(context, 0, audio);

    }


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

        this.position = position;

        if (itemView == null) {
            itemView = LayoutInflater.from(getContext())
                    .inflate(R.layout.audio_tab_item, parent, false);

            holder = new ViewHolder();

            holder.audioView = (ImageView) itemView.findViewById(R.id.audio_icon);
            audioTitleView = (TextView) itemView.findViewById(R.id.audio_title);

            // stores holder with view
            itemView.setTag(holder);

        } else {

            holder = (ViewHolder)itemView.getTag();
        }

        // get position of the item clicked in GridView
        final AudioGridItem audioGridItem = getItem(position);

        if (audioGridItem != null) {
            Uri audioUri = audioGridItem.getAudio();
            String audioTitle = audioGridItem.getAudioTitle();
            String rootName = FilenameUtils.removeExtension(audioTitle);

            Log.d("TAG", "Value of audioTitle: " + audioTitle);

            Log.d("TAG", "Value of rootName: " + rootName);

            // set the photos into the ImageView slots
            holder.audioView.setImageURI(audioUri);
            audioTitleView.setText(rootName);

            // positioning the image in the GridView slot
            holder.audioView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            holder.audioView.setLayoutParams(new LinearLayout.LayoutParams
                    (250, 250));
        }

        return itemView;

    }

    public class ViewHolder{
        ImageView audioView;
    }
}

日志

package org.azurespot.cutecollection.audiotab;

import android.net.Uri;

/**
 * Created by mizu on 4/26/15.
 */
public class AudioGridItem {

    private Uri audio;
    private String audioTitle;

    public AudioGridItem(Uri audio, String autoTitle) {
        super();
        this.audio = audio;
        this.audioTitle = autoTitle;
    }

    public Uri getAudio() {

        return audio;
    }

    public void setAudio(Uri audio){

        this.audio = audio;
    }

    public String getAudioTitle(){

        return audioTitle;
    }

    public void setAudioTitle(String audioTitle){

        this.audioTitle = audioTitle;

    }

}

1 个答案:

答案 0 :(得分:1)

检查出来

 audioAdapter = new GridViewAudioAdapter(getActivity(), audioFiles);

以上行audioFiles为空ArrayList,而您的audioAdapter正在将其视为备用人..现在,在您的retrieveAudio()方法中,您将项目添加到{ {1}}这样audioFiles现在audioFiles.add(audioGridItem);包含1个项目, - (假设这是您添加的唯一项目),但在您audioFiles调用中执行此操作

onPostExecute

您现在已将Log.d("TAG", "Items in audioFiles: " + audioFiles.size()); // Add whole ArrayList to adapter audioAdapter.addAll(audioFiles); //pay attention here Log.d("TAG", "Number of item in audioAdapter2: " + audioAdapter.getCount()); 添加到audioFiles,并在文档addAll(collection) 中为audioFiles提供了总共两项,最后添加指定的集合数组意味着它不会替换它,所以你要做的就是忘记GridView添加并使用onPostExecute逐个添加项目并调用{{ 1}}因为你无法在doInBackground中调用它