Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 拖到绘图完成后。为什么?_Android_Android Layout - Fatal编程技术网

Android 拖到绘图完成后。为什么?

Android 拖到绘图完成后。为什么?,android,android-layout,Android,Android Layout,2012年8月5日上午7:23更新: 我尝试交换draw/toast,即将draw放在AsyncTask中,将toast放在主UI线程中,但仍然没有乐趣:行为没有改变。我放弃了。但是,谢谢大家的建议。 -约翰 ====================================== 2012年4月5日下午6:30更新: 我认为“单任务”问题可能是问题所在,工作线程可能会工作,但由于根据定义,两个线程都需要访问UI(主线程),因此在我看来,似乎仍然存在争用。尽管如此,根据建议,我在AsyncT

2012年8月5日上午7:23更新:
我尝试交换draw/toast,即将draw放在AsyncTask中,将toast放在主UI线程中,但仍然没有乐趣:行为没有改变。我放弃了。但是,谢谢大家的建议。
-约翰

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

2012年4月5日下午6:30更新:
我认为“单任务”问题可能是问题所在,工作线程可能会工作,但由于根据定义,两个线程都需要访问UI(主线程),因此在我看来,似乎仍然存在争用。尽管如此,根据建议,我在AsyncTask的onProgressUpdate()中添加了toast,但正如我所担心的,问题仍然存在。(我不想将渲染放在异步任务中,因为它是一个怪物,我更愿意将简单的toast放在另一个任务中)。所以,还是没有快乐。关于如何做到这一点,还有其他建议吗

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

我创建了一个应用程序,可以在屏幕上合成并绘制位图。因为合成位图需要2-3秒,所以我想向用户显示一条Toast消息,如“刷新,请待机…”。我的问题是,即使我在drawBitmap()之前调用toast(),toast直到绘制完成后才会显示

我以前在Windows下见过类似的行为,因为消息队列在长时间计算期间备份,所以解决方案是在长时间计算期间定期显式地分派消息。但我不知道是否/如何在Android上实现这一点。也许是神秘的“活套”

我已经包括了一个小的,琐碎的应用程序来隔离/演示这个问题

非常感谢您的建议。
-约翰

自定义视图:

//  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();
    }
}
//PixmapView-我的自定义视图
公共类PixmapView扩展了视图{
静态最终整数宽=1000,高=1000,大小=(宽*高);
静态int切换;
//构造一个视图以显示pixmap
公共PixmapView(上下文ctx、属性集属性){
超级(ctx、ATTR);
}
//处理onDraw回调
@凌驾
受保护的void onDraw(画布){
int[]pixmap;
位图bm;
super.onDraw(帆布);
吐司(“提神…”);
pixmap=createPixmap();
bm=Bitmap.createBitmap(pixmap,宽,高,Bitmap.Config.ARGB_8888);
drawBitmap(bm,0,0,null);
}
//创建一个pixmap
int[]createPixmap()
{
int i,颜色;
国际[]下午;;
双s;
Random rand=新的Random();
pm=newint[Size];//分配pixmap
切换++;
如果((切换&1)==0)颜色=0xff0000ff;//红色
else color=0xffff0000;//蓝色

对于(i=0;i两者在UI上是唯一的,它们之间没有延迟,因此您只能在两者结束后才能看到修改。

您在与Toast消息相同的线程上调用画布刷新。由于重画操作会阻止UI线程,直到它完成为止,因此在UI线程解除阻止之前无法呈现Toast消息。如果如果将重画操作移动到工作线程中,应该可以解决问题。

您应该将长时间运行的任务从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();
}
私有类DrawAsyncTask扩展了AsyncTask{
int[]pixmap;
位图bm;
受保护的空位背景(空位…v){
pixmap=createPixmap();
bm=Bitmap.createBitmap(pixmap,宽,高,Bitmap.Config.ARGB_8888);
返回bm;
}
受保护的void onPostExecute(位图[]结果){
drawBitmap(结果[0],0,0,null);
}
}
受保护的void onDraw(画布){
super.onDraw(帆布);
吐司(“提神…”);
新建DrawAsyncTask().execute();
}

我遇到了类似的问题。在我的例子中,我正在加载谷歌地图。第一次加载谷歌地图时,由于api密钥的验证过程以及加载初始地图图像,会出现明显的延迟。这可能需要几秒钟的时间,并且不会显示toast。一个简单的解决方案是使用地图加载AsyncTask或单独的活动,但不是,以立即启动AsyncTask或活动,但延迟1秒。首先显示toast,然后在延迟后启动流程:

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

谢谢lenik,我会试试的。在我之前的尝试中,我把绘图放在主UI任务中,然后旋转toast。我会按照你的建议用另一种方式尝试并发布结果。没有理由把
toast
放在
AsyncTask
中——它不需要任何重要的时间,在UI线程上运行得很好。你需要的是放入
AsyncTask
的对象是长时间运行的任务,如文件访问、网络访问、复杂计算或数据处理。
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();
}
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)
    {
    }
  }
};