0

フォルダ内のサウンド ファイルの ListView で、ファイルの長さを秒単位で表示したいと考えています。私が取る手順:

  1. 最初に、soundFiles のインスタンスの ArrayList を作成します。
  2. 次に for ループで、soundFile.setLength(calculateLength(file[i])) によってデータをインスタンスに追加します。
  3. この後、CustomArrayAdapter を開始し、それを listView に適用します。
  4. 私の CustomArrayAdapter では、それを適用します: tvFileLength.setText(soundFile.getLength()); (ホルダー付きですが..)

しかし、私はこれをやっているので、私のアプリはタートルよりも遅いです! (400 個のファイルがあります) この速度を修正する方法はありますか?

private int calculateLength(File yourFile)
            throws IllegalArgumentException, IllegalStateException, IOException {
        MediaPlayer mp = new MediaPlayer();
        FileInputStream fs;
        FileDescriptor fd;
        fs = new FileInputStream(yourFile);
        fd = fs.getFD();
        mp.setDataSource(fd);
        mp.prepare(); 
        int length = mp.getDuration();
        length = length / 1000;
        mp.release();
        return length;

    }

   **EDIT**

私が持っている新しいコード:

アクティビティ

myList = new ArrayList<RecordedFile>();

        File directory = Environment.getExternalStorageDirectory();
        file = new File(directory + "/test/");

        File list[] = file.listFiles();

        for (int i = 0; i < list.length; i++) {
            if (checkExtension(list[i].getName()) == true) {

                RecordedFile q = new RecordedFile();
                q.setTitle(list[i].getName());
                q.setFileSize(readableFileSize(list[i].length()));
                            //above is the size in kB, is something else but I 
                            //also might move this to the AsyncTask!


                myList.add(q);
            }
        }
        new GetAudioFilesLength(myList).execute();

非同期タスク

List<RecordedFile> mFiles = new ArrayList<RecordedFile>();

    public GetAudioFilesLength(List<RecordedFile> theFiles) {
        mFiles = theFiles;
    }

    @Override
    protected String doInBackground(Void... params) {

        File directory = Environment.getExternalStorageDirectory();
        // File file = new File(directory + "/test/");
        String mid = "/test/";

        for (RecordedFile fileIn : mFiles) {

            File file = new File(directory + mid + fileIn.getTitle());
            try {
                int length = readableFileLengthSeconds(file);
                fileIn.setFileLengthSeconds(length);
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalStateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // Do something with the length


            // You might want to update the UI with the length of this file
            // with onProgressUpdate so that you display the length of the files
            // in real time as you process them.
        }
        return mid;

    }

    @Override
    protected void onProgressUpdate(Void... values) {

    }

    @Override
    protected void onPostExecute(String result) {
        // Update the UI in any way you want. You might want
        // to store the file lengths somewhere and then update the UI
        // with them here
    }

    /*
     * @Override protected void onPreExecute() { }
     */

    public int readableFileLengthSeconds(File yourFile)
            throws IllegalArgumentException, IllegalStateException, IOException {
        MediaPlayer mp = new MediaPlayer();
        FileInputStream fs;
        FileDescriptor fd;
        fs = new FileInputStream(yourFile);
        fd = fs.getFD();
        mp.setDataSource(fd);
        mp.prepare(); // might be optional
        int length = mp.getDuration();
        length = length / 1000;
        mp.release();
        return length;

    }

素晴らしい、部分的には機能しますが!残りの 2 つの質問があります。

  1. これは問題なく効率的に見えますか?
  2. リストビューの最初の 100 要素で動作し、その後 0 が表示され、onProgressUpdate と関係があると思いますが、どうすればこれを機能させることができるかわかりません。
4

1 に答える 1

1

MediaPlayer が継続時間を検出できるようにファイルを読み込むには、明らかに時間がかかります。これを UI スレッドで実行しているため、アプリケーション全体の速度が低下します。

プロセスを高速化する方法についての提案はありませんが、AsyncTask を使用してバックグラウンド スレッドでこの作業を行うと、アプリケーションをよりスムーズに動作させることができます。それは次のようになります。

private class GetAudioFilesLength extends AsyncTask<Void, Void, Void> {

      List<File> mFiles = new ArrayList<File>();

      public GetAudioFilesLength(List<File> theFiles){
           mFiles = theFiles;
      }

      @Override
      protected String doInBackground(String... params) {
            for(File file : mFiles){
                int length = calculateLength(file);
                // Do something with the length

                // You might want to update the UI with the length of this file
                // with onProgressUpdate so that you display the length of the files
                // in real time as you process them.
            }
      }      

      @Override
      protected void onPostExecute(String result) {
            // Update the UI in any way you want. You might want
            // to store the file lengths somewhere and then update the UI
            // with them here
      }

      @Override
      protected void onPreExecute() {
      }

      @Override
      protected void onProgressUpdate(Void... values) {
      }
}   

処理を開始したいときは、呼び出すだけですnew GetAudioFilesLength(files).execute()

追加の質問に答えるために編集します。

  1. 元のコードと同じくらい効率的に見えます。現在の違いは、作業がバックグラウンド スレッドで行われるため、ユーザーは引き続きアプリケーションを操作できることです。オーディオ ファイルの長さを読み取るためのより効率的な方法がある可能性がありますが、それが何であるかはわかりません。サンプル レートとエンコーディングを知っていれば、時間がかかる MediaPlayer に読み込まずにオーディオの長さを計算するコードを記述できると想像できます。繰り返しますが、他の誰かがそれを手伝わなければなりません。

  2. 問題が何であるかはわかりませんが、onProgressUpdate を使用して UI を更新し、長さを ListView に追加する方法を尋ねていると思いますか?

AsyncTask 生成の中間引数を doInBackground の String (またはその他)AsyncTask<Void, String, Void>, that tells onProgressUpdate what you will be passing to it. You can then callの publishProgress` に変更して、それに応じて UI を更新することができます。

@Override
  protected String doInBackground(Void... params) {
        for(File file : mFiles){
            int length = calculateLength(file);
            // Do something with the length

            // You might want to update the UI with the length of this file
            // with onProgressUpdate so that you display the length of the files
            // in real time as you process them.
            publishProgress("The length of " + file.getName() + " is: " + length);
        }
  }      

  @Override
  protected void onPostExecute(Void result) {
        // Update the UI in any way you want. You might want
        // to store the file lengths somewhere and then update the UI
        // with them here
  }

  @Override
  protected void onProgressUpdate(String... values) {
        // You'll have to implement whatever you'd like to do with this string on the UI
        doSomethingWithListView(values[0]);
  }
于 2013-04-12T17:05:00.000 に答える