2012-01-05 7 views
0

私はsqliteデータベースをtableLayoutに読み込んでいます。私は、Uiの更新がなくても長時間待機するのではなく、別のスレッドでこれを行うのをやめてしまいました。そこで、AsyncTaskを使用して作業の一部を行い、結果を公開しました。しかし、私のリストにあるアイテムの約1/4しか実際にはTableLayoutに表示されません。 AsyncTaskなしで正常に動作します。リストのほとんどの項目はエラー(java.util.concurrent.RejectedExecutionException)をスローします。なぜこのことが分かりませんか?ここに私のコードです。asyncTaskからjava.util.concurrent.RejectedExecutionExceptionをアンドロイドで取得する

myDB.execSQL("CREATE TABLE IF NOT EXISTS " 
       + TableName 
       + " (_id INTEGER PRIMARY KEY, filepath TEXT UNIQUE, title TEXT, artist TEXT, album TEXT, time TEXT, playcount NUMERIC);"); 

     Cursor c = myDB.rawQuery("SELECT * FROM " + TableName, null);   

     c.moveToFirst(); 
     if (c != null) { 
      int color = 0xFFdfe8ea; 
      this.startManagingCursor(c); 
      // Loop through all Results 
      do { 
       try{ 
        MyAsyncTask aTask = new MyAsyncTask(); 
        String[]strings= {c.getString(c.getColumnIndex("title")),c.getString(c.getColumnIndex("artist")),c.getString(c.getColumnIndex("time")),c.getString(c.getColumnIndex("album")),""+color}; 
        aTask.execute(strings); 
       }catch(Exception e){ 
        Log.w("****", e); 
       } 
     if (color == 0xFFdfe8ea) { 
        color = 0xFFf2f8fa; 
       } else { 
        color = 0xFFdfe8ea; 
       } 
      } while (c.moveToNext()); 
     } 

    } catch (SQLException e) { 
     Log.e("****", e.toString()); 
    } finally { 
     if (myDB != null) { 
      myDB.close(); 
     } 
    } 

と、ここで、これは私はそれを修正する方法です参考のためAsyncTask

class MyAsyncTask extends AsyncTask<String, Void, View> { 
    @Override 
    protected View doInBackground(String... params) { 
     int color = Integer.parseInt(params[4]); 

     TableRow tr = new TableRow(MainActivity.this); 
     tr.setLayoutParams(new LayoutParams(
       LayoutParams.FILL_PARENT, 
       LayoutParams.WRAP_CONTENT)); 

     TextView space = new TextView(MainActivity.this); 
     space.setText(""); 
     space.setBackgroundColor(color); //0xFFf2f8fa alternating 
     space.setSingleLine(); 
     space.setPadding(2, 2, 2, 2); 
     space.setGravity(Gravity.LEFT); 
     space.setTextColor(0xFF000000); 
     space.setLayoutParams(new LayoutParams(
       findViewById(R.id.spaceColumn).getWidth(), 
       LayoutParams.WRAP_CONTENT)); 

     /* Create a Button to be the row-content. */ 
     TextView title = new TextView(MainActivity.this); 
     title.setText(params[0]); 
     title.setBackgroundColor(color); //0xFFf2f8fa alternating 
     title.setSingleLine(); 
     title.setPadding(2, 2, 2, 2); 
     title.setGravity(Gravity.LEFT); 
     title.setTextColor(0xFF000000); 
     title.setEllipsize(TruncateAt.END); 
     title.setLayoutParams(new LayoutParams(
       0, 
       LayoutParams.WRAP_CONTENT, 1)); 

     /* Create a Button to be the row-content. */ 
     TextView artist = new TextView(MainActivity.this); 
     artist.setText(params[1]); 
     artist.setBackgroundColor(color); //0xFFf2f8fa alternating 
     artist.setSingleLine(); 
     artist.setPadding(2, 2, 2, 2); 
     artist.setGravity(Gravity.LEFT); 
     artist.setTextColor(0xFF000000); 
     artist.setEllipsize(TruncateAt.END); 
     artist.setLayoutParams(new LayoutParams(
       0, 
       LayoutParams.WRAP_CONTENT, 1)); 

     /* Create a Button to be the row-content. */ 
     TextView time = new TextView(MainActivity.this); 
     time.setText(params[2]); 
     time.setBackgroundColor(color); //0xFFf2f8fa alternating 
     time.setSingleLine(); 
     time.setPadding(2, 2, 2, 2); 
     time.setGravity(Gravity.LEFT); 
     time.setTextColor(0xFF000000); 
     time.setLayoutParams(new LayoutParams(
       findViewById(R.id.timeColumn).getWidth(), 
       LayoutParams.WRAP_CONTENT)); 

     /* Create a Button to be the row-content. */ 
     TextView album = new TextView(MainActivity.this); 
     album.setText(params[3]); 
     album.setBackgroundColor(color); //0xFFf2f8fa alternating 
     album.setSingleLine(); 
     album.setPadding(2, 2, 2, 2); 
     album.setGravity(Gravity.LEFT); 
     album.setTextColor(0xFF000000); 
     album.setEllipsize(TruncateAt.END); 
     album.setLayoutParams(new LayoutParams(
       0, 
       LayoutParams.WRAP_CONTENT, 1)); 

     /* Add Button to row. */ 
     tr.addView(space); 
     tr.addView(title); 
     tr.addView(artist); 
     tr.addView(time); 
     tr.addView(album); 

     /* Add row to TableLayout. */ 
     return tr; 
    } 

    @Override 
    protected void onPostExecute(View tr) { 
     ((TableLayout) findViewById(R.id.tableLayout)).addView(tr, new TableLayout.LayoutParams(
         LayoutParams.FILL_PARENT, 
         LayoutParams.WRAP_CONTENT)); 
    } 

    @Override 
    protected void onPreExecute() { 
    } 
} 

です。

class MyAsyncTask extends AsyncTask<Void, Song, Void> { 

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

     SQLiteDatabase myDB = openOrCreateDatabase("DatabaseName", MODE_PRIVATE, null); 
     String TableName = "songs"; 

     myDB.execSQL("CREATE TABLE IF NOT EXISTS " 
       + TableName 
       + " (_id INTEGER PRIMARY KEY, filepath TEXT UNIQUE, title TEXT, artist TEXT, album TEXT, time TEXT, playcount NUMERIC);"); 

     Cursor c = myDB.rawQuery("SELECT * FROM " + TableName, null); 

     c.moveToFirst(); 
     int filepathIndex=c.getColumnIndex("filepath"); 
     int titleIndex=c.getColumnIndex("title"); 
     int artistIndex=c.getColumnIndex("artist"); 
     int albumIndex=c.getColumnIndex("album"); 
     int timeIndex=c.getColumnIndex("time"); 
     int playcountIndex=c.getColumnIndex("playcount"); 

     if (c != null) { 
      int color = 0xFFdfe8ea; 
     // this.startManagingCursor(c); 
      // Loop through all Results 
      do { 
       Song song = new Song(c.getString(filepathIndex),c.getString(titleIndex),c.getString(artistIndex),c.getString(albumIndex),c.getString(timeIndex),c.getInt(playcountIndex),color); 
       // Add to song the data from your cursor 
       publishProgress(song); 

       if (color == 0xFFdfe8ea) { 
        color = 0xFFf2f8fa; 
       } else { 
        color = 0xFFdfe8ea; 
       } 
      } while (c.moveToNext()); 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void item) { 
    } 

    @Override 
    protected void onPreExecute() { 
    } 

    @Override 
    protected void onProgressUpdate(Song... items) { 
     for (Song song : items) { 
      TableRow tr = new TableRow(MainActivity.this); 
      tr.setLayoutParams(new LayoutParams(
        LayoutParams.FILL_PARENT, 
        LayoutParams.WRAP_CONTENT)); 

      TextView space = new TextView(MainActivity.this); 
      space.setText(""); 
      space.setBackgroundColor(song.color); //0xFFf2f8fa alternating 
      space.setSingleLine(); 
      space.setPadding(2, 2, 2, 2); 
      space.setGravity(Gravity.LEFT); 
      space.setTextColor(0xFF000000); 
      space.setLayoutParams(new LayoutParams(
        findViewById(R.id.spaceColumn).getWidth(), 
        LayoutParams.WRAP_CONTENT)); 

      /* Create a Button to be the row-content. */ 
      TextView title = new TextView(MainActivity.this); 
      title.setText(song.title); 
      title.setBackgroundColor(song.color); //0xFFf2f8fa alternating 
      title.setSingleLine(); 
      title.setPadding(2, 2, 2, 2); 
      title.setGravity(Gravity.LEFT); 
      title.setTextColor(0xFF000000); 
      title.setEllipsize(TruncateAt.END); 
      title.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Create a Button to be the row-content. */ 
      TextView artist = new TextView(MainActivity.this); 
      artist.setText(song.artist); 
      artist.setBackgroundColor(song.color); //0xFFf2f8fa alternating 
      artist.setSingleLine(); 
      artist.setPadding(2, 2, 2, 2); 
      artist.setGravity(Gravity.LEFT); 
      artist.setTextColor(0xFF000000); 
      artist.setEllipsize(TruncateAt.END); 
      artist.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Create a Button to be the row-content. */ 
      TextView time = new TextView(MainActivity.this); 
      time.setText(song.time); 
      time.setBackgroundColor(song.color); //0xFFf2f8fa alternating 
      time.setSingleLine(); 
      time.setPadding(2, 2, 2, 2); 
      time.setGravity(Gravity.LEFT); 
      time.setTextColor(0xFF000000); 
      time.setLayoutParams(new LayoutParams(
        findViewById(R.id.timeColumn).getWidth(), 
        LayoutParams.WRAP_CONTENT)); 

      /* Create a Button to be the row-content. */ 
      TextView album = new TextView(MainActivity.this); 
      album.setText(song.album); 
      album.setBackgroundColor(song.color); //0xFFf2f8fa alternating 
      album.setSingleLine(); 
      album.setPadding(2, 2, 2, 2); 
      album.setGravity(Gravity.LEFT); 
      album.setTextColor(0xFF000000); 
      album.setEllipsize(TruncateAt.END); 
      album.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Add Button to row. */ 
      tr.addView(space); 
      tr.addView(title); 
      tr.addView(artist); 
      tr.addView(time); 
      tr.addView(album); 

      // Add the row to the table 
      ((TableLayout) findViewById(R.id.tableLayout)).addView(tr, new TableLayout.LayoutParams(
        LayoutParams.FILL_PARENT, 
        LayoutParams.WRAP_CONTENT)); 
     } 
    } 
} 
+2

UIスレッドの外部からビューを作成しないでください。 doInBackground()ではSQLクエリを実行できますが、onPostExecute()ではビューを作成できます。 –

+0

@ ghostbust555どのバージョンをお使いですか? –

答えて

1

あなたはAsyncTaskを使ってそれを実行したい場合は、publishProgress()の使用を検討し、それがデータベースからフェッチされるよう、その方法は、各項目が追加されます。この方法:

Songnamealbumartisttime属性を持つクラスであることを考えてみましょう。私はあなたが間違ってAsyncTaskの背後にある概念を理解して信じて

class MyAsyncTask extends AsyncTask<Void, Song, Void> { 
    @Override 
    protected Void doInBackground(Void... params) { 
     myDB.execSQL("CREATE TABLE IF NOT EXISTS " 
      + TableName 
      + " (_id INTEGER PRIMARY KEY, filepath TEXT UNIQUE, title TEXT, artist TEXT, album TEXT, time TEXT, playcount NUMERIC);"); 

     Cursor c = myDB.rawQuery("SELECT * FROM " + TableName, null);   

     c.moveToFirst(); 
     if (c != null) { 
      int color = 0xFFdfe8ea; 
      this.startManagingCursor(c); 
      // Loop through all Results 
      do { 
       Song song = new Song(); 
       // Add to song the data from your cursor 
       publishProgress(song); 
      } while (c.moveToNext()); 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void item) { 
    } 

    @Override 
    protected void onPreExecute() { 
    }  

    @Override 
    protected void onProgressUpdate(Song... items) { 
     for (Song song : items) {  
      TableRow tr = new TableRow(MainActivity.this); 
      tr.setLayoutParams(new LayoutParams(
        LayoutParams.FILL_PARENT, 
        LayoutParams.WRAP_CONTENT)); 

      TextView space = new TextView(MainActivity.this); 
      space.setText(""); 
      space.setBackgroundColor(color); //0xFFf2f8fa alternating 
      space.setSingleLine(); 
      space.setPadding(2, 2, 2, 2); 
      space.setGravity(Gravity.LEFT); 
      space.setTextColor(0xFF000000); 
      space.setLayoutParams(new LayoutParams(
        findViewById(R.id.spaceColumn).getWidth(), 
        LayoutParams.WRAP_CONTENT)); 

      /* Create a Button to be the row-content. */ 
      TextView title = new TextView(MainActivity.this); 
      title.setText(song.getTitle()); 
      title.setBackgroundColor(color); //0xFFf2f8fa alternating 
      title.setSingleLine(); 
      title.setPadding(2, 2, 2, 2); 
      title.setGravity(Gravity.LEFT); 
      title.setTextColor(0xFF000000); 
      title.setEllipsize(TruncateAt.END); 
      title.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Create a Button to be the row-content. */ 
      TextView artist = new TextView(MainActivity.this); 
      artist.setText(song.getArtist()); 
      artist.setBackgroundColor(color); //0xFFf2f8fa alternating 
      artist.setSingleLine(); 
      artist.setPadding(2, 2, 2, 2); 
      artist.setGravity(Gravity.LEFT); 
      artist.setTextColor(0xFF000000); 
      artist.setEllipsize(TruncateAt.END); 
      artist.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Create a Button to be the row-content. */ 
      TextView time = new TextView(MainActivity.this); 
      time.setText(song.getTime()); 
      time.setBackgroundColor(color); //0xFFf2f8fa alternating 
      time.setSingleLine(); 
      time.setPadding(2, 2, 2, 2); 
      time.setGravity(Gravity.LEFT); 
      time.setTextColor(0xFF000000); 
      time.setLayoutParams(new LayoutParams(
        findViewById(R.id.timeColumn).getWidth(), 
        LayoutParams.WRAP_CONTENT)); 

      /* Create a Button to be the row-content. */ 
      TextView album = new TextView(MainActivity.this); 
      album.setText(song.getAlbum()); 
      album.setBackgroundColor(color); //0xFFf2f8fa alternating 
      album.setSingleLine(); 
      album.setPadding(2, 2, 2, 2); 
      album.setGravity(Gravity.LEFT); 
      album.setTextColor(0xFF000000); 
      album.setEllipsize(TruncateAt.END); 
      album.setLayoutParams(new LayoutParams(
        0, 
        LayoutParams.WRAP_CONTENT, 1)); 

      /* Add Button to row. */ 
      tr.addView(space); 
      tr.addView(title); 
      tr.addView(artist); 
      tr.addView(time); 
      tr.addView(album); 

      // Add the row to the table 
      ((TableLayout) findViewById(R.id.tableLayout)).addView(tr, new TableLayout.LayoutParams(
          LayoutParams.FILL_PARENT, 
          LayoutParams.WRAP_CONTENT)); 
     } 
    } 
} 

、私は強くあなたがそうするとき、その概念は少し理解するのが難しいが、非常に強力であるとして、あなたがits documentation at Android Developersを再読示唆しています。 Romain Guyがあなたの答えにコメントしたので、onPreExecute()、onProgressUpdate()およびonPostExecute()メソッドでのみUIコードを実行できます。

+0

明確にするには、publishUpdate(曲)publishProgress(曲)が正しいはずですか? – ghostbust555

+0

はい、私は自分の答えを編集しました。 –

+0

ありがとう、これは私の問題を解決しました。 – ghostbust555

0

私はそれのために1つのAsyncTaskを作成する必要はないと思います。あなたはネットワークや画像のダウンロードから何も取得していません。その標準的な読み込みです。

SQLの結果を 'limit'で制限します。

また、アダプターの内部でこれを実行していますか?私はリストにすべてを追加していると思うので、レイアウトでリストビューを作成してアダプタを設定する必要があります。たぶんBaseAdapterを拡張します。

すべてのアダプターには、getViewと呼ばれる便利なメソッドがあります。このメソッドは、表示されているときにのみ呼び出され、問題に役立つはずです。

これは、アダプタの例です:

public class MyAdapter extends BaseAdapter { 

    private Context context = null; 
    private Cursor cursor; 

    public MyAdapter(Context context){ 

     this.context = context;  
     SQLiteDatabase db = DatabaseHelper.getInstance(context).getReadableDatabase();    
     this.cursor = db.query("YOUR QUERY"); 

    } 

    @Override 
    public int getCount() { 
     return this.cursor.getCount(); 
    } 


    public Cursor getCursor() { 
     return cursor; 
    } 

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

     LinearLayout row; 

     try {   
     cursor.moveToPosition(position); 

     if (convertView == null) {  
      row = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.myRowLayout, parent, false); 
      } else { 
      row = (LinearLayout) convertView; 
      } 

     TextView name = (TextView) row.findViewById(R.id.myLayoutId); 
     name.setText(cursor.getString(cursor.getColumnIndex("your column"))); 

     } catch (Exception e) { 
      row = null; 
      Log.e(LOG_TAG, "" + e.getMessage()); 
      e.printStackTrace(); 
     } 

     return row; 

    } 

    @Override 
    public MoneyCurrency getItem(int position) {   
     this.cursor.moveToPosition(position); 
     long id = this.cursor.getLong(this.cursor.getColumnIndex("your column id")); 
     return new Object.read(id, context, null); //Return whatever you want to show in that row. This is used if you want to use onClick listeners or menus 
    } 

    @Override 
    public long getItemId(int position) { 
     this.cursor.moveToPosition(position); 
     return this.cursor.getLong(this.cursor.getColumnIndex("your id column")); 
    } 



    } 
+0

私はListViewでTableLayoutを使用していますが(何とかリストビューに切り替えることを検討していましたが)、別のスレッドにしたいので、非常に大きなデータベースがあると15秒間黒い画面が表示されません。行を追加してその行を表示し、繰り返します。 – ghostbust555

+0

リストビューの各項目に対してTableLayoutを設定できます。しかし、AsyncTaskの外側でカーソルを照会していることを確認してください。そうすれば、アダプターを使用している場合や、プロセスを実行して表を埋める場合でも実行されます。リストビューを使用するほうがはるかに効率的です。データベースが大きすぎる場合、リストビューやアダプタのスレッドを使用すると、おそらくどちらかの方法で制限する必要があるので、あまり役に立ちません。別のスレッドで何をしたいかは、アダプタのgetView内で動作します。意味がありますか? – sfratini

2

このRejectedExceutionExceptionが表示される理由は、あまりにも多くのリクエストを送信しているためです。

私はAsyncTaskのコードに行き、私は気づいた:有界LinkedBlockingQueueを構築します

private static final int CORE_POOL_SIZE = 5; 
private static final int MAXIMUM_POOL_SIZE = 128; 
private static final int KEEP_ALIVE = 1; 

private static final BlockingQueue<Runnable> sPoolWorkQueue = 
     new LinkedBlockingQueue<Runnable>(10); 

/** 
* An {@link Executor} that can be used to execute tasks in parallel. 
*/ 
    public static final Executor THREAD_POOL_EXECUTOR 
      = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, 
        TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); 

。バインドの要素は最大10個です。私が見た MAXIMUM_POOL_SIZEは128です(これは、必要に応じて、Executorが最大で128のスレッドを作成することを意味します)。

128スレッドを超えて、キュー深度10の新しいMyTaskインスタンスに送信すると、RejectedExecutionExceptionが発生します。この例外は、使用可能なすべてのスレッドを飽和させ、キューに余裕がない場合にスローされます。

RejectedExecutionが発生したときにスレッドダンプを取得することで、これを簡単に確認できます。

基本的に、あなたは、任意の特定の時間に138のMyTaskに年代を提出することができますが、あなたは(ないアプリのライフタイム内で)同時に139+送信すると、あなたは、この問題に実行されます

編集:私はコードをより多く、そして最も最近のバージョン(2011年1月16日から実際に)このエラーは決して起こるべきではありません。

これより古いバージョンの場合は、このissueに実行されます。

要するに、バージョンをアップグレードするとこの問題は解消されますが、各タスクは連続して実行され、同時に実行されることはありません。

+0

このエラーは10個のAsyncTasksを呼び出すと発生し、かなり新しいバージョンですが、私は更新と報告を試みます。 – ghostbust555

+0

スタックトレースを含めることはできますか –

関連する問題