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.