Android View Canvas Ondraw Not Performed
Solution 1:
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()
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!
Take a look at the explanation of AsyncTask methods here:
When an asynchronous task is executed, the task goes through 4 steps:
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...), 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...), 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), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
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.
Solution 2:
Have you heard of a method call setWillNotDraw(boolean)?
Check it out here
Set it to false and you'll see
Solution 3:
Just to save this for the future and possible google searchers ;)
I made a new Class which provides datas for my View. This class extends Thread and runns in the background. It checks which tiles my view has to display.
Long story short: Each time a new tile has to be displayed my provider class collects some update requests. If 3 or more update requests are "collected" or it is more than 1 second since the first update request the view will get view.postInvalidate().
The problem was that a view ignores some invalidate requests if you fire several of them at once. If you collect those invalidate requests and fire several of them with just one invalidate() you can see the newest information with just a small lag of time - but you can see it ;)
Solution 4:
I've solved the problem requesting view.invalidate()
or view.postInvalidate()
not for invalidating every child view individually (each of these child views incorporated its own AsyncTask), but for invalidating their common parent ViewGroup.
Now in details. I had
publicclassmViewGroupextendsRelativeLayout {...}
and several Views in it, each View as follows:
publicclassmViewextendsView {
privatemViewGroupmContext=null;
//with a little bit modified standard constructors:publicmView(Context context, mViewGroup ParentViewGroup) {
super(context);
mContext = ParentViewGroup;
}
//and also with an AsyncTask:privateclassmViewAsyncTaskextendsAsyncTask<Integer, Void, Void> {
publicmAsyncTask() {
@Overrideprotected Void doInBackground(Integer... a) {
//which does its work and sometimes publishes progress:
publishProgress();
returnnull;
}
protectedvoidonProgressUpdate(Void... progress) {
invalidate();
}
}
The calls to invalidate();
sometimes worked and sometimes didn't (may be in cases if calls were made from different AsyncTask
s belonging to different mView
s but in very close moments of time).
Changing
invalidate(); //i.e. invalidating individual View
to
mContext.invalidate(); //i.e. invalidating the whole ViewGroup
solved the problem.
Solution 5:
In my case, target custom View has height = 0 attribute at that time.(My mistake) and postInvalidate() and invalidate didn't fired onDraw() and Log too.
When I changed height currectly, all problem solved.
Post a Comment for "Android View Canvas Ondraw Not Performed"