View刷新
2016-05-26 11:33
197 查看
在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。postinvaliate()可以在分线程刷新invaliate()只能在主线程中执行横竖屏切换的时候一定会刷新View1.不使用多线程和双缓冲 这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。
/** * Invalidate the whole view. If the view is visible, * {@link #onDraw(android.graphics.Canvas)} will be called at some point in * the future. * <p> * This must be called from a UI thread. To call from a non-UI thread, call * {@link #postInvalidate()}. */ public void invalidate() { invalidate(true); }
@Override protected void onDraw(Canvas canvas) { if (canvas instanceof HardwareCanvas) { HardwareCanvas hwCanvas = (HardwareCanvas) canvas; mView.mRecreateDisplayList = true; RenderNode renderNode = mView.getDisplayList(); if (renderNode.isValid()) { hwCanvas.insertReorderBarrier(); // enable shadow for this rendernode hwCanvas.drawRenderNode(renderNode); hwCanvas.insertInorderBarrier(); // re-disable reordering/shadows } } }2.使用多线程和不使用双缓冲 这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views. 这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量, 你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。
/** * 要在Activity中开启一个用于更新的线程 * timeViewHandler 继承自Handler,用于处理和发送消息 * MSG_UPDATE 是自定义的一个int常量,用于区分消息类型,可自由取值。 */ new Thread(new Runnable() { @Override public void run() { while(true){ try { timeViewHandler.sendMessage(Message.obtain(timeViewHandler, MSG_UPDATE)); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
/** * Handler示例,用于刷新时间 */ public class TimeViewHandler extends Handler { private TextView timeView; public TextView getTimeView() { return timeView; } public void setTimeView(TextView timeView) { this.timeView = timeView; } public TimeViewHandler(TextView timeView) { super(); this.timeView = timeView; } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE: timeView.setText(DateHelper.getNow("kk:mm:ss")); timeView.invalidate(); break; } super.handleMessage(msg); } }
3.使用多线程和双缓冲Android中SurfaceView是View的子类,她同时也实现了双缓冲。也可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。/*** SurfaceView使用示例,TouchDrawView主要完成屏幕的指尖绘画*/public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback{private SurfaceHolder holder;private TouchDrawListener listener;public TouchDrawListener getListener() {return listener;}public void setListener(TouchDrawListener listener) {this.listener = 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);this.setOnTouchListener(listener);//设置屏幕事件监听器this.setLongClickable(true);//不设置将无法捕捉onFling()事件setFocusable(true);//设置键盘焦点setFocusableInTouchMode(true);//设置触摸屏焦点}public TouchDrawView(Context context, AttributeSet as) {this(context);}@Overrideprotected void onDraw(Canvas canvas) {}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//关键部分Canvas canvas = holder.lockCanvas(null);//获取画布canvas.drawColor(Color.WHITE);//白色背景holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}}
使用postInvalidate()刷新界面使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。
class GameThread implements Runnable {public void run() {while (!Thread.currentThread().isInterrupted()) {try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 使用postInvalidate可以直接在线程中更新界面mGameView.postInvalidate();}}}
相关文章推荐
- Android View刷新机制实例分析
- Xcode真机调试出现 “Could not find Developer Disk Image”
- 聊天对话反馈到ListView,点击读取
- iOS开发~UITableView区头跟随移动
- map,mulitmap,set,mulitset,unordered_map,unorderer_set
- Android、ios 音频编解码 音频口通信 音频通信
- 专业技能
- K好数
- Java HashCode详解
- try catch finally执行顺序和return值
- 教你如何添加Xcode 9.3配置包?(安装流程可供其他版本安装参考)
- 找水王2
- nginx + fastDFS 设置开机自动启动
- ASP.NET Web API 使用Swagger生成在线帮助测试文档
- Java Set转List,排序,去重
- 日常解决的细节
- HttpClient 传输xml字符串
- 个人用户目录通过rysnc迁移
- LeetCode:Interleaving String
- Gradle编译错误