简体   繁体   中英

Multiple duplicates load into GridView from SD card

I am trying to load Uri sound files from my SD card into a custom GridView where each item contains an ImageView (for the Uri ) and a TextView for the sound file title, but it keeps loading duplicates. I have 6 sound files on my card, but it loads 12, then very oddly another 3 after all the drawables load. The drawables (placeholder images) load fine, they load the right number.

I put a lot of the file I/O into an AsyncTask , but I doubt this would cause any problems like this.

When I log everything, I see things getting unexpectedly loaded a few times (console below), including odd null values. I have other working code with the exact same process, except loading images instead of sound files, and it works perfectly, so this is really puzzling. I realize loading Uri s into a GridView is not ideal, as there is nothing to see in the ImageView , but when I click on each item, it does play the file, so that part is correct. I will rework the image problem later.

Any idea why things are loading so strangely in duplicates? Thanks.

UPDATE

It turns out since I had the ArrayList<AudioGridItem> in my adapter constructor, that any change to my list was automatically updating, so I didn't need to add it again to the adapter manually. So I just deleted the adding to adapter in my onPostExecute() and it worked!

@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();

        }

在此处输入图片说明

AudioTab.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();
                    }
                }
            }

        });
    }
}

GridViewAudioAdapter.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;
    }
}

Here is my model: AudioGridItem.java

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;

    }

}

Logs

04-27 16:46:56.406  24668-24668/org.azurespot D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
04-27 17:04:28.176  24668-24668/org.azurespot D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
04-27 17:04:28.326  24668-24668/org.azurespot D/TAG﹕ Items in audioAdapter1: 0
04-27 17:04:28.376  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.376  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.386  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.386  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.446  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.446  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.446  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.446  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.466  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.466  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.466  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound66.3gpp
04-27 17:04:28.466  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound66
04-27 17:04:28.476  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound19.3gpp
04-27 17:04:28.476  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound19
04-27 17:04:28.476  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound47.3gpp
04-27 17:04:28.486  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound47
04-27 17:04:28.486  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound49.3gpp
04-27 17:04:28.486  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound49
04-27 17:04:28.486  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound51.3gpp
04-27 17:04:28.486  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound51
04-27 17:04:28.606  24668-24668/org.azurespot D/TAG﹕ Items in audioFiles: 6
04-27 17:04:28.606  24668-24668/org.azurespot D/TAG﹕ Number of item in audioAdapter2: 12
04-27 17:04:28.606  24668-24668/org.azurespot D/TAG﹕ Number of item in audioAdapter3: 21
04-27 17:04:28.606  24668-24668/org.azurespot D/TAG﹕ Number of items in SD Card files: 6
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.616  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound66.3gpp
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound66
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound19.3gpp
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound19
04-27 17:04:28.626  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound47.3gpp
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound47
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound49.3gpp
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound49
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound51.3gpp
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound51
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound66.3gpp
04-27 17:04:28.636  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound66
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound19.3gpp
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound19
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound47.3gpp
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound47
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound49.3gpp
04-27 17:04:28.646  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound49
04-27 17:04:28.656  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound51.3gpp
04-27 17:04:28.656  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound51
04-27 17:04:28.656  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:28.656  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:28.666  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:28.666  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:28.666  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:28.666  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:29.876  24668-24668/org.azurespot D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: null
04-27 17:04:30.516  24668-24668/org.azurespot D/TAG﹕ Value of rootName: null
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound54.3gpp
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound54
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound66.3gpp
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound66
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of audioTitle: Sound19.3gpp
04-27 17:04:31.696  24668-24668/org.azurespot D/TAG﹕ Value of rootName: Sound19

Check this out

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

the above line audioFiles is an empty ArrayList and your audioAdapter is looking to it as his backup man.. Now in your retrieveAudio() method you add items to audioFiles like this audioFiles.add(audioGridItem); now audioFiles contains 1 item, -(suppose that is the only item you add) but in your onPostExecute you call do this

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());

you have now added audioFiles to audioFiles giving you a total of two items in your GridView from the documentation addAll(collection) Adds the specified Collection at the end of the array which means it does not replace it, so what you got to do is forget about the onPostExecute adding and use on onProgressUpdate to add the item one by one and call notifyDatasetChanged() because you can't call it in the doInBackground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM