UPDATE 05/08/12 7:23 AM:
我尝试交换绘制/吐司,即将Draw放入主UI线程中的AsyncTask和Toast中,但仍然没有乐趣:行为没有变化。我放弃。但是,感谢大家的建议
-John
======================================
更新05/04/12 6:30 PM:
我认为“单任务”问题可能是问题,工作线程可能会工作,但由于两个线程按定义都需要访问UI(主线程),所以在我看来我仍然会有争用。尽管如此,根据建议,我将 toast 放在AsyncTask的onProgressUpdate()中,但是,正如我所担心的那样,问题仍然存在。 (我不想把渲染放在一个异步任务中,因为它是一个怪物,我更喜欢把简单的吐司放在另一个任务中)。所以,仍然没有快乐。关于如何做到这一点的任何其他建议?
======================================
我创建了一个应用程序,它将位图组合并绘制到屏幕上。因为组合位图需要2-3秒,我想向用户显示Toast消息,如“刷新,请待机......”。我的问题是,即使我在 drawBitmap()之前调用Toast(),只要在之后油漆完成,吐司才会显示。
我之前在Windows下看到过这样的行为,因为消息队列在长时间计算期间得到了备份,解决方案是定期在长时间计算期间明确地调度消息。但我无法弄清楚是否/如何在Android上执行此操作。也许是神秘的(对我来说)“Looper”???
我已经包含了一个小的,琐碎的应用程序隔离/演示问题。
任何建议非常赞赏 -John
// 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>
答案 0 :(得分:1)
您正在与Toast消息相同的线程上调用画布的刷新。由于重绘操作会阻止UI线程直到完成,因此无法呈现Toast消息,直到UI线程被解除阻塞。如果将重绘操作移动到工作线程中,它应该可以解决您的问题。
答案 1 :(得分: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();
}
答案 2 :(得分:0)
两者都在UI上播放,它们之间没有延迟,所以只有在两个结束后才能看到修改。
答案 3 :(得分:0)
我有类似的问题。就我而言,我正在加载谷歌地图。第一次加载Google地图时,由于api密钥的验证过程以及加载初始地图图像,会出现明显的延迟。这可能需要几秒钟的时间,并且不会显示吐司。一个简单的解决方案是将地图加载到AsyncTask或单独的Activity中,但 NOT 立即加载AsyncTask或Activity,但是在延迟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)
{
}
}
};