问题描述
我目前正在使用自定义视图,该视图在画布上绘制一些图块.这些磁贴将从多个文件加载,并将在需要时加载.
I am currently working on a custom View which draws some tiles on the canvas.Those tiles are loaded from several files and will be loaded when needed.
它们将由AsyncTask加载.如果它们已经被加载,它们将被绘制在画布上. 这正常工作!
They will be loaded by an AsyncTask. If they are already loaded they will just be painted on the canvas. This is working properly!
如果加载了这些图片,则AsyncTask将触发 view.postInvalidate()问题在于,每次触发view.postInvalidate()时,我的自定义视图不会触发 onDraw(画布画布).
If those pictures are loaded the AsyncTask is firing view.postInvalidate()The problem is that my custom View is not firing onDraw(Canvas canvas) everytime I fire view.postInvalidate().
view.postInvalidate 仅在加载图片时才第一次触发onDraw()方法,然后仅当我在内部的onTouchEvent中触发this.invalidate()时才触发我的CustomView
The view.postInvalidate only fires onDraw() method the first time when a picture is loaded and then only when I fire this.invalidate() in an onTouchEvent inside my CustomView
View是否可能决定是否再次绘制画布?有没有一种方法可以强制重绘视图?我认为invalidate方法告诉View如果View考虑重新绘制-.-
Is it possible that a View decides wether it will draw the canvas again or not?Is there a way to FORCE the View to redraw? I think the invalidate method tells the View that it would be cool if the View would think about redrawing -.-
那些无效方法是否有限制?
Is it possible that those invalidate methods have a limit?
希望大家对这个问题有更多的了解.
I hope anyone of you knows more about this problem.
我只是将每个postInvalidate()更改为 invalidate(),因为图像都是由从主线程执行的AsyncTask加载的但是仍然存在一个问题,即执行的 invalidate()没有执行 onDraw()方法.我发现通过覆盖原始方法触发了 view.invalidate():
I just changed every postInvalidate() to invalidate() because the images are all loaded by an AsyncTask executed from the main ThreadBut there is still the problem that an executed invalidate() is not executing the onDraw() method.I found out that the view.invalidate() is fired by overriding the original method:
@Override
public void invalidate() {
super.invalidate();
Log.d(TAG, "invalidate executed");
}
我现在不知道该怎么办.我正在触发view.invalidate()和view.postInvalidate(),但是没有任何组合绝对无效.
I don't know what to do now. I'm firing view.invalidate() and view.postInvalidate() but nothing works in absolutely no combination.
推荐答案
这里有些误解. invalidate和postInvalidate方法用于告知View,需要在最早的绘制周期中对其进行刷新和重绘.区别在于,invalidate方法应从UI线程内部调用,而postInvalidate应从UI线程外部调用.
There's a bit of a misunderstanding here. The invalidate and postInvalidate method are used to tell the View that it needs to be refreshed and redrawn in the earliest drawing cycle. The difference is that the invalidate method should be called from within the UI Thread and the postInvalidate should be called from outside of the UI Thread.
以下简要介绍了这些方法:
These methods are briefly described here:
- http://developer.android.com/reference/android/view/View.html#postInvalidate()
- http://developer.android.com/reference/android/view/View.html#invalidate()
- http://developer.android.com/reference/android/view/View.html#postInvalidate()
- http://developer.android.com/reference/android/view/View.html#invalidate()
AsyncTask 是专门设计的类针对您面临的问题.当您需要在后台执行大型任务时,异步地需要AsyncTask,但是! AsyncTask的回调方法在UIThread中运行!
The AsyncTask on the other hand is a class devised especially for the problem you're facing. When you need to perform a big task in the background, asynchronously you need the AsyncTask for that, but! the AsyncTask's callback method is run in the UIThread!
在这里看一下AsyncTask方法的说明:
Take a look at the explanation of AsyncTask methods here:
执行异步任务时,该任务将经历4个步骤:
When an asynchronous task is executed, the task goes through 4 steps:
-
onPreExecute(),在执行任务后立即在UI线程上调用.此步骤通常用于设置任务,例如,通过在用户界面中显示进度栏.
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params ...),在onPreExecute()完成执行后立即在后台线程上调用.此步骤用于执行可能需要很长时间的后台计算.异步任务的参数将传递到此步骤.计算结果必须通过此步骤返回,并将传递回最后一步.此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单位.这些值在onProgressUpdate(Progress ...)步骤中发布在UI线程上.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress ...),在调用publishProgress(Progress ...)之后在UI线程上调用.执行的时间是不确定的.此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度.例如,它可以用于为进度栏设置动画或在文本字段中显示日志.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result),在后台计算完成之后在UI线程上调用.后台计算的结果作为参数传递到此步骤.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
这意味着在onPostExecute方法中,您应该尝试使用invalidate方法而不是从UIThread调用的postInvalidate方法.
This means that in the onPostExecute method you should try using the invalidate method instead of the postInvalidate method as it is called from the UIThread.
这篇关于未执行Android View Canvas onDraw的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!