博客
关于我
Android多线程与双缓冲
阅读量:626 次
发布时间:2019-03-14

本文共 3440 字,大约阅读时间需要 11 分钟。

Android视图更新有多种方法,具体使用时要根据需求选择合适的方式。以下是几种常见的情况,帮助开发者更好地理解和使用。

1. 不使用多线程和双缓冲

这种情况最简单,也是最常用的。只需要在Activity中显式调用View对象的invalidate()方法,系统会自动触发View的onDraw()方法进行重绘。

优点:代码简单,容易实现。

缺点:当View内容频繁更新时,可能会由于线程 invalide() 在不同线程中导致UI更新异常。

示例代码:

public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        final TextView TextView = (TextView) findViewById(R.id.TextView);                new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    TextView.invalidate();                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();    }}

2. 使用多线程但不使用双缓冲

这种情况需要在新线程中执行UI更新操作,但直接访问View对象会导致异常(CalledFromWrongThread)。

解决方法是使用Handler类进行消息传递和UI更新。具体步骤如下:

  • 创建一个继承自Handler的子类,用于处理UI更新任务。
  • 在新线程中发送具有特定标识符的消息。
  • 在Handler中接收消息并调用View的invalidate()方法。
  • 示例代码:

    public class TimeViewHandler extends Handler {    private TextView timeView;        public TimeViewHandler(TextView timeView) {        super();        this.timeView = timeView;    }        @Override    public void handleMessage(Message msg) {        if (msg.what == MSG_UPDATE) {            timeView.setText(DateHelper.getNow("kk:mm:ss"));            timeView.invalidate();        }        super.handleMessage(msg);    }}public class MainActivity extends Activity {    private static final int MSG_UPDATE = 123;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        final TextView TextView = (TextView) findViewById(R.id.TextView);        final TimeViewHandler handler = new TimeViewHandler(TextView);                new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    handler.sendEmptyMessage(MSG_UPDATE);                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();    }}

    3. 使用多线程和双缓冲

    如果需要更高频率的UI更新而避免因多线程操作导致的性能问题,可以使用SurfaceView和双缓冲的组合。

    SurfaceView是View的子类,同时实现了双缓冲功能。通过继承SurfaceHolder.Callback接口,可以在新线程中直接进行绘制操作,而无需通过Handler。

    优点:支持高频率的渲染和动画效果,适合需要复杂图形操作的场景。

    示例代码:

    public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback {    private SurfaceHolder holder;    private TouchDrawListener listener;        public TouchDrawView(Context context) {        super(context);        holder = getHolder();        holder.addCallback(this);        listener = new TouchDrawListener(holder);        listener.setShape(TouchDrawListener.SHAPE_LINE);        listener.setShape_style(TouchDrawListener.SHAPE_STYLE_FILL);        setOnClickListener(listener);        setLongClickable(true);        setFocusable(true);        setFocusableInTouchMode(true);    }        @Override    public void surfaceCreated(SurfaceHolder holder) {        Canvas canvas = holder.lockCanvas(null);        canvas.drawColor(Color.WHITE);        holder.unlockCanvasAndPost(canvas);    }}

    通过以上方法,开发者可以根据具体需求选择合适的View更新方式。在需要高频率更新或复杂图形处理时,可以选择多线程加双缓冲的方案;在简单场景中直接使用主线程的invalidate()方法即可满足需求。

    转载地址:http://deroz.baihongyu.com/

    你可能感兴趣的文章
    ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED
    查看>>
    BUU-MISC-caesar
    查看>>
    【专题3:电子工程师 之 上位机】 之 【46.QT音频接口】
    查看>>
    一文理解设计模式--命令模式(Command)
    查看>>
    VTK:可视化之RandomProbe
    查看>>
    block多队列分析 - 2. block多队列的初始化
    查看>>
    Java时间
    查看>>
    不编译只打包system或者vendor image命令
    查看>>
    The wxWindows Library Licence (WXwindows)
    查看>>
    【编程】C语言入门:1到 100 的所有整数中出现多少个数字9
    查看>>
    flink启动(二)
    查看>>
    关于宝塔面板安装的mysql用Navicat连接出现2003的错误解决
    查看>>
    pair的用法
    查看>>
    Flex 布局的自适应子项内容过长导致其被撑大问题
    查看>>
    PL/SQL 动态Sql拼接where条件
    查看>>
    Lua-table 一种更少访问的安全取值方式
    查看>>
    虚函数
    查看>>
    Error:Cannot read packageName from AndroidManifest.xml
    查看>>
    【自学Flutter】4.1 Material Design字体图标的使用(icon)
    查看>>
    【换行符】什么时候用cin.get()吃掉输入流中的换行符
    查看>>