首页 文章

Android View Canvas onDraw未执行

提问于
浏览
2

我目前正在开发一个自定义视图,它在画布上绘制一些图块 . 这些图块从多个文件加载,并在需要时加载 .

它们将由AsyncTask加载 . 如果它们已经加载,它们将被画在画布上 . This is working properly!

如果这些图片被加载,AsyncTask正在触发 view.postInvalidate() 问题是我每次触发view.postInvalidate()时自定义View is not firing onDraw(Canvas画布) .

view.postInvalidate 仅在加载图片时触发onDraw()方法 the first time ,然后仅在我在CustomView内的onTouchEvent中触发this.invalidate()时触发

是否有可能视图决定是否再次绘制画布?有没有办法让 FORCE 视图重绘?我认为invalidate方法告诉View,如果View考虑重绘,那将会很酷.-

这些无效方法是否有可能有限制?

我希望你们中的任何人都能更多地了解这个问题 .

edit:

我刚刚将 every postInvalidate() 更改为 invalidate() 因为图像全部由从主线程执行的AsyncTask加载但仍然存在执行 invalidate() 未执行 onDraw() 方法的问题 . 我发现 view.invalidate() 是通过覆盖原始方法来解雇的:

@Override
public void invalidate() {
    super.invalidate();
    Log.d(TAG, "invalidate executed");
}

我现在不知道该怎么办 . 我正在触发view.invalidate()和view.postInvalidate(),但绝对没有任何组合 .

5 回答

  • 0

    只为了将来保存这个以及可能的谷歌搜索者;)

    我创建了一个新的Class,为我的View提供数据 . 这个类扩展了Thread并在后台运行 . 它会检查我的视图必须显示哪些图块 .

    长话短说:每次必须显示新的磁贴时,我的提供者类会收集一些更新请求 . 如果“收集”3个或更多更新请求,或者自第一个更新请求起超过1秒,则视图将获得view.postInvalidate() .

    问题是,如果一次触发多个请求,视图将忽略一些无效请求 . 如果你收集那些无效的请求并用一个invalidate()激活其中几个,你可以看到最新的信息只有一小段时间 - 但你可以看到它;)

  • 1

    这里有一点误会 . invalidate和postInvalidate方法用于告诉View它需要在最早的绘图周期中刷新和重绘 . 不同之处在于应该从UI线程中调用invalidate方法,并且应该从UI线程外部调用postInvalidate .

    这里简要描述了这些方法:

    另一方面,AsyncTask是一个专为您在UIThread中运行're facing. When you need to perform a big task in the background, asynchronously you need the AsyncTask for that, but! the AsyncTask'回调方法的问题设计的类!

    在这里看一下AsyncTask方法的解释:

    执行异步任务时,任务将执行4个步骤:

    onPreExecute(),在执行任务后立即在UI线程上调用 . 此步骤通常用于设置任务,例如通过在用户界面中显示进度条 . doInBackground(Params ...),在onPreExecute()完成执行后立即在后台线程上调用 . 此步骤用于执行可能需要很长时间的后台计算 . 异步任务的参数将传递给此步骤 . 计算结果必须由此步骤返回,并将传递回最后一步 . 此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单元 . 这些值发布在UI线程的onProgressUpdate(Progress ...)步骤中 . onProgressUpdate(Progress ...),在调用publishProgress(Progress ...)后在UI线程上调用 . 执行的时间是不确定的 . 此方法用于在后台计算仍在执行时显示用户界面中的任何形式的进度 . 例如,它可用于为进度条设置动画或在文本字段中显示日志 . onPostExecute(Result),在后台计算完成后在UI线程上调用 . 背景计算的结果作为参数传递给该步骤 .

    这意味着在onPostExecute方法中,您应该尝试使用invalidate方法而不是从UIThread调用的postInvalidate方法 .

  • 1

    你听说过方法调用setWillNotDraw(boolean)吗?

    看看here

    将它设置为false,你会看到

  • 0

    我已经解决了请求 view.invalidate()view.postInvalidate() 的问题,而不是单独使每个子视图无效(这些子视图中的每一个都包含其自己的AsyncTask),但是为了使它们的公共父ViewGroup无效 .

    现在详细说明 . 我有

    public class mViewGroup extends RelativeLayout {...}
    

    其中有几个视图,每个视图如下:

    public class mView extends View {
    
    private mViewGroup mContext = null;
    
    //with a little bit modified standard constructors:
    public mView (Context context, mViewGroup ParentViewGroup) {
            super(context);
            mContext = ParentViewGroup;
    }
    
    //and also with an AsyncTask:
    private class mViewAsyncTask extends AsyncTask<Integer, Void, Void> {
    public mAsyncTask() {
       @Override
       protected Void doInBackground(Integer... a) {
           //which does its work and sometimes publishes progress:
           publishProgress();
           return null;
       }
    
       protected void onProgressUpdate(Void... progress) {
           invalidate();
       }
    
    }
    

    invalidate(); 的调用有时是有效的,有时则没有(如果来自不同的 AsyncTask 的调用属于不同的 mView ,但是在非常接近的时刻时间) .

    更改

    invalidate(); //i.e. invalidating individual View
    

    mContext.invalidate(); //i.e. invalidating the whole ViewGroup

    解决了这个问题 .

  • 0

    在我的情况下,目标自定义View在那时具有height = 0属性 . (我的错误)和postInvalidate()和invalidate没有触发onDraw()和Log .

    当我当前改变高度时,所有问题都解决了 .

相关问题