1

我想從我的SD卡Uri聲音文件加載到自定義GridView,其中每個項目包含ImageView(爲Uri)和聲音文件標題TextView,但它一直加載重複。我的卡上有6個聲音文件,但它加載了12個,然後非常奇怪的是在所有可繪製加載之後的另外3個文件。 drawables(佔位符圖像)加載正常,它們加載正確的數字。多重複加載到GridView控件從SD卡

我把很多文件I/O放入AsyncTask,但我懷疑這會導致這樣的問題。

當我記錄所有東西時,我發現事情意外加載了幾次(下面的控制檯),包括奇數空值。除了加載圖片而不是聲音文件之外,我還有其他工作代碼,具有完全相同的過程,並且它完美地工作,所以這真是令人費解。我意識到加載Uri s到GridView並不理想,因爲在ImageView中沒有什麼可以看到的,但是當我點擊每個項目時,它確實播放該文件,因此該部分是正確的。稍後我會重新處理圖像問題。

任何想法爲什麼事情加載如此奇怪的重複?謝謝。

UPDATE

原來,因爲我在我的轉接器構造的ArrayList<AudioGridItem>,任何改變我的名單自動更新,所以我沒有必要再手動將其添加到適配器。所以我剛剛刪除了在我的onPostExecute()中的適配器添加,它工作!

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

     } 

enter image description here

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

這裏是我的模式L: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; 

    } 

} 

日誌

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 

回答

1

檢查了這一點

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

上面的一行audioFiles是一個空ArrayList和你audioAdapter正在以它作爲他的備份人..現在,在您的retrieveAudio()方法將項目添加到audioFiles這樣audioFiles.add(audioGridItem);現在audioFiles包含1項, - (假設是你加的唯一項目),但在你的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()); 

現在你已經添加audioFilesaudioFiles從文檔addAll(collection)給你GridView總共有兩個項目這意味着它不會取代它,所以你要做的就是忘記onPostExecute添加和使用在onProgressUpdate上添加該項目一個接一個,並致電notifyDatasetChanged(),因爲你不能在doInBackground中調用它

+0

感謝Elitz,但是當你說我將'audioFiles'添加到'audioFiles'時,我看不到如何,因爲我將'audiodio'對象添加到'audioAdapter '有一個空的'ArrayList' ...它是如何添加2個副本的? (也許再解釋一下,謝謝)。 – Azurespot

+1

我的意思是你的gridview指向'audioFiles'作爲它的數據源,並且在你的doinbackground的'retrieveAudio()'方法中,你將這些項添加到'audioFiles'這意味着如果你添加了10個項目,你的gridview將顯示10個項目,所以現在你有10個項目,那麼你在你的'postExecute'中添加項目到10個指向適配器中的或引用'audioFiles'的項目,並且通過addAll定義它不能取代'audioFiles',但它添加'audioFiles'結尾的項目。 @NoniA。 – Elltz

+0

_continuation_ - 所以你已經添加了10個項目到'audioFiles',這10個項目是'audioFiles',這是'audioFiles'的一個重複,因此你已經添加'audioFiles'到'audioFiles',得到我?你想讓我爲你重新編寫解決方案代碼嗎? @NoniA。 – Elltz