Android 中的线程 UI 更新 [英] Threading UI updates in Android

查看:28
本文介绍了Android 中的线程 UI 更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始使用 android 开发,更新 UI 真的让我很烦恼:/

这就是我目前所做的工作 -

<前>打包项目.移动;导入 android.os.Bundle;导入 android.view.View;导入 android.app.Activity;导入 android.content.Context;导入 android.graphics.Canvas;导入 android.graphics.Paint;导入 android.graphics.Color;公共类移动扩展活动{私人浮动 y = 0;现在私人多头 = 0;私人浮动延迟 = 75;私人油漆油漆 = 新油漆();@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SimpleMotion(this));Paint.setColor(Color.BLACK);}私有类 SimpleMotion 扩展视图 {公共 SimpleMotion(上下文上下文){超级(上下文);}@Override protected void onDraw(Canvas canvas) {浮动 x = canvas.getWidth()/2;canvas.drawColor(Color.WHITE);canvas.drawCircle(x, y, 30, 油漆);if(System.currentTimeMillis() - now > delay) y++;无效();}}}

它工作正常,但每个人都说在主线程中做你的图形,所以我试图(但失败)将它传递给另一个线程.问题是,我完全不知道是怎么回事,因为我从来没有使用过线程.

Google 提供的关于使用 Threads 的示例似乎不是很清楚,我无法真正按照我想要做的事情来遵循它.我可以请这里的人给我一个最基本的例子,说明我如何使用 Threads 有效地完成我在这里所做的事情吗?

提前致谢:)

解决方案

好吧,我想这里有些混乱.您必须从主线程(也称为 GUI 线程)执行 GUI 更新 - 否则您会得到类似异常,blabla 已泄露视图"之类的信息.

我想误解的是昂贵的操作,例如网络,应该在与主线程不同的线程中完成.如果您想从网络线程更新 GUI,您可以按照 ArtWorkAD 所说(或他的链接所说)进行操作.

因此,对于您想要执行的操作,您可以使用以下内容替换 SimpleMotion 类:

private class SimpleMotion extends View {公共 SimpleMotion(上下文上下文){超级(上下文);新线程(新运行(){公共无效运行(){而(真){尝试 {线程睡眠(75);y++;postInvalidate();} catch (InterruptedException e) {e.printStackTrace();}}}}).开始();}@Override protected void onDraw(Canvas canvas) {浮动 x = canvas.getWidth()/2;canvas.drawColor(Color.WHITE);canvas.drawCircle(x, y, 30, 油漆);//if(System.currentTimeMillis() - now > delay) y++;//无效();}}

使用 invalidate()onDraw() 中的旧代码,即使没有更改,您也会不断重绘 gui.

新代码的重要部分是postInvalidate().这使得告诉 GUI 线程(来自另一个线程)重新绘制 GUI 成为可能.

I've just started with android development and updating the UI is really bugging me :/

This is what I've got working so far -


package projects.Move;

import android.os.Bundle;
import android.view.View;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Color;

public class Move extends Activity {

    private float y = 0;
    private long now = 0;  
    private float delay = 75;
    private Paint paint = new Paint();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SimpleMotion(this));
        paint.setColor(Color.BLACK);
    }
    private class SimpleMotion extends View {

        public SimpleMotion(Context context) {
            super(context);
        }

        @Override protected void onDraw(Canvas canvas) {

            float x = canvas.getWidth() / 2;
            canvas.drawColor(Color.WHITE);
            canvas.drawCircle(x, y, 30, paint);  
            if(System.currentTimeMillis() - now > delay) y++;    
            invalidate();
        }
    }
}

It works fine but everybody says that doing your graphics in the main thread, so I'm trying (and failing) to pass it off to another thread. Trouble is, I have absolutely no idea how since really I've never used Threads.

The examples that Google gives on using Threads doesn't seem to be very clear and I couldn't really follow it for what I want to do. Could I ask somebody out here to give me the most basic example of how I could do what I'm doing here efficiently using Threads?

Thanks in advance :)

解决方案

Well, I guess there is some confusion going on here. You HAVE TO do your GUI updates from the main thread (also called the GUI thread) - otherwise you well get something like "Exception, blabla has leaked a view".

I guess what have misunderstood is that expensive operations, such as networking, should be done in a different thread than the main thread. And if you would like to update the GUI from the network thread you would do as ArtWorkAD says (or his links says).

So for what you want to do, you could achieve with something like replacing your SimpleMotion class with the following:

private class SimpleMotion extends View {

        public SimpleMotion(Context context) {
            super(context);

            new Thread(new Runnable() {
                public void run() {
                    while(true){
                        try {
                            Thread.sleep(75);
                            y++;
                            postInvalidate();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
              }).start();
        }

        @Override protected void onDraw(Canvas canvas) {

            float x = canvas.getWidth() / 2;
            canvas.drawColor(Color.WHITE);
            canvas.drawCircle(x, y, 30, paint);  
//            if(System.currentTimeMillis() - now > delay) y++;    
//            invalidate();
        }
    }

With your old code of having invalidate() in onDraw() you would continously be redrawing the gui even while there are no change to it.

The important part of the new code is postInvalidate(). This makes it possible to tell the GUI thread - from another thread - to redraw the GUI.

这篇关于Android 中的线程 UI 更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆