0

UPDATE 05/08/12 7:23 AM:
ドロー/トーストを交換しようとしました。つまり、ドローをAsyncTaskに入れ、トーストをメインUIスレッドに入れましたが、それでも喜びはありませんでした。動作に変化はありません。あきらめる。しかし、提案してくれたすべての人に感謝します。
-ジョン

======================================

UPDATE 05/04/12 6:30 PM:
「シングルタスク」の問題が問題であり、ワーカースレッドが機能する可能性があると思いましたが、定義上、両方のスレッドがUI(メインスレッド)にアクセスする必要があるため、私にはまだ論争があるように。それでも、提案に基づいて、トーストをAsyncTaskのonProgressUpdate()に入れましたが、恐れていたように、問題は解決しません。(それはモンスターであり、他のタスクに単純なトーストを入れる方が快適だったので、レンダリングを非同期タスクに入れたくありませんでした)。だから、まだ喜びはありません。これを行う方法に関する他の提案はありますか?

======================================

ビットマップを作成して画面に描画するアプリケーションを作成しました。ビットマップの作成には2〜3秒かかるため、「リフレッシュしてください、スタンバイしてください...」などのトーストメッセージをユーザーに表示したいと思います。私の問題は、 drawBitmap( )の前にToast()を呼び出しても、ペイントが完了するまでトーストが表示されないことです。

以前、Windowsでこのような動作が見られたのは、長い計算中にメッセージキューがバックアップされたためです。解決策は、長い計算中にメッセージを定期的に明示的にディスパッチすることでした。しかし、Androidでこれを行うかどうか/方法がわかりません。多分不思議な(私にとって)「ルーパー」???

問題を切り分け/実証する、小さくて些細なアプリを含めました。

どんな提案でも大歓迎です。
-ジョン

//  PixmapTestMain.java

public class PixmapTestMain extends Activity {

public static View PixmapView;                  // pixmap view
public static Context Ctx;

// Create activity
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Ctx = this;
    PixmapView = findViewById( R.id.pixmap );
}

// Handle click
public void onClick(View v) {           // button view clicked
    PixmapView.invalidate();            // new pixmap
}

}  // end class PixmapTestMain

カスタムビュー:

//  PixmapView - my custom view

public class PixmapView extends View {

static final int Wide=1000,High=1000,Size=(Wide*High);
static int toggle;

// Construct a view to display pixmap
public PixmapView(Context ctx,AttributeSet attrs) {
    super(ctx, attrs);
}

// Handle onDraw callback
@Override
protected void onDraw( Canvas canvas) {
    int[] pixmap;
    Bitmap bm;

    super.onDraw(canvas);

    toast( "Refreshing..." );
    pixmap = createPixmap();
    bm = Bitmap.createBitmap( pixmap, Wide, High, Bitmap.Config.ARGB_8888 );
    canvas.drawBitmap( bm, 0, 0, null );
}

// Create a pixmap
int[] createPixmap()
{
    int i,color;
    int[] pm;
    double s;
    Random rand = new Random();

    pm = new int[Size];                     // allocate pixmap

    toggle++;
    if( (toggle&1)==0 ) color = 0xff0000ff; // red
    else                color = 0xffff0000; // blue

    for( i=0; i<Size; i++ ) {
        pm[i] = color;
        rand.nextLong();        // slow me down
    }

    return( pm );
}

// Flash a toast message
public void toast( String msg)
{
    if( PixmapTestMain.Ctx == null ) return;
    Toast.makeText( PixmapTestMain.Ctx, msg, 0 ).show();
    }
}

レイアウト:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<Button
  android:text="Refresh"
  android:id="@+id/refresh"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="onClick"/>

<com.hyperdyne.PixmapTest.PixmapView
  android:id="@+id/pixmap"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"/>

</LinearLayout>
4

4 に答える 4

1

Toastメッセージと同じスレッドでキャンバスの更新を呼び出しています。再描画操作は、完了するまでUIスレッドをブロックするため、UIスレッドのブロックが解除されるまで、トーストメッセージをレンダリングできません。再描画操作をワーカースレッドに移動すると、問題が解決するはずです。

于 2012-05-04T19:12:14.060 に答える
1

実行時間の長いタスクをUIスレッドから移動する必要があります。次に例を示します。

protected void onDraw( Canvas canvas) {
    int[] pixmap;
    Bitmap bm;

    super.onDraw(canvas);

    toast( "Refreshing..." );
    pixmap = createPixmap();
    bm = Bitmap.createBitmap( pixmap, Wide, High, Bitmap.Config.ARGB_8888 );
    canvas.drawBitmap( bm, 0, 0, null );
}

次のようになります。

private class DrawAsyncTask extends AsyncTask<Void,Void,Bitmap[]> {
    int[] pixmap;
    Bitmap bm;

    protected Void doInBackground(Void... v) {
        pixmap = createPixmap();
        bm = Bitmap.createBitmap( pixmap, Wide, High, Bitmap.Config.ARGB_8888 );
        return bm;
    }

    protected void onPostExecute(Bitmap[] result) {
        canvas.drawBitmap( result[0], 0, 0, null );
    }
}

protected void onDraw( Canvas canvas) {
    super.onDraw(canvas);
    toast( "Refreshing..." );
    new DrawAsyncTask().execute();
}
于 2012-05-04T23:14:38.420 に答える
0

どちらもUIで問題なく動作するため、両方の終了後にのみ変更が表示されます。

于 2012-05-04T16:26:34.420 に答える
0

私も同様の問題を抱えていました。私の場合、Googleマップを読み込んでいます。Googleマップを初めて読み込むときは、APIキーの確認プロセスと、最初の地図画像の読み込みが原因で、大幅な遅延が発生します。これには数秒かかる場合があり、トーストは表示されません。簡単な解決策は、AsyncTaskまたは別のアクティビティのいずれかにマップをロードすることですが、 AsyncTaskまたはアクティビティをすぐに起動するのではなく、1秒の遅延後に起動します。最初にトーストを表示し、しばらくしてからプロセスを起動します。

Toast.makeText(context, "Please wait...", Toast.LENGTH_LONG).show();
Handler handler = new Handler(); handler.postDelayed(DoSomething, 1000);

private Runnable DoSomething = new Runnable()
{
  @Override
  public void run()
  {
    try
    {
      // Launch an AsyncTask here or some other activity to handle your long process.
    }
    catch (Exception ex)
    {
    }
  }
};
于 2013-01-04T15:56:14.843 に答える