在onDraw()中使用线程

时间:2014-03-31 15:38:48

标签: android multithreading ondraw

我正在编写一个应用程序,我有一个自定义视图。在这个自定义视图中,我必须计算未确定点数的位置。点数取决于我从数据库中读取的内容(因此每个用户的内容都不同)。 所以,我的问题是,我怎样才能以一种好的方式解决这个问题呢?该应用程序的步骤如下:

  1. 活动开始
  2. 数据库查询
  3. 图纸
  4. 问题是当我打开活动时会调用onDraw() - 方法,但我无法绘制任何内容,因为我必须等待数据库查询和点的计算。在计算完成之前,我怎样才能使用线程和类似进度条的东西?我可以阻止应用在活动开始时立即运行onDraw() - 方法吗?

    感谢您的帮助。

    edit1:所以这里是代码(注意:我现在不想计算任何东西,出现错误是因为我试图将ProgressBar的可见性设置为true,而不使用此行):< / p>

        public class MyView extends View {
        private ProgressBar progressBar;
        private boolean calculationsDone;
    
        public MyView(Context context, AttributeSet attrs) {
                super(context);
                // TODO Auto-generated constructor stub
    
                progressBar = (ProgressBar) findViewById(R.id.progressBar1);
                calculationsDone=false;
            }
    
        protected void onDraw(final Canvas canvas) {
                super.onDraw(canvas);
    
    
                if(calculationsDone == true){
                    //draw stuff
                    progressBar.setVisibility(INVISIBLE);
                }else{
                    Log.d("calcNotDone", "CALCULATION NOT DONE YET!");
                    progressBar.setVisibility(VISIBLE);
                }
    
            }
    
        }
    

    以下是错误:

      

    03-31 20:45:44.131:E / AndroidRuntime(27445):致命异乎寻常:主要   03-31 20:45:44.131:E / AndroidRuntime(27445):   java.lang.NullPointerException 03-31 20:45:44.131:   E / AndroidRuntime(27445):at   com.example.test.MyView.onDraw(MyView.java:50)03-31 20:45:44.131:   E / AndroidRuntime(27445):在android.view.View.draw(View.java:14853)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13744)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13786)03-31 20:45:44.131:   E / AndroidRuntime(27445):在android.view.View.draw(View.java:14563)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.drawChild(ViewGroup.java:3316)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.draw(View.java:14856)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13744)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13786)03-31 20:45:44.131:   E / AndroidRuntime(27445):在android.view.View.draw(View.java:14563)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.drawChild(ViewGroup.java:3316)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13739)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13786)03-31 20:45:44.131:   E / AndroidRuntime(27445):在android.view.View.draw(View.java:14563)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.drawChild(ViewGroup.java:3316)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13739)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13786)03-31 20:45:44.131:   E / AndroidRuntime(27445):在android.view.View.draw(View.java:14563)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.drawChild(ViewGroup.java:3316)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.draw(View.java:14856)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.widget.FrameLayout.draw(FrameLayout.java:467)03-31   20:45:44.131:E / AndroidRuntime(27445):at   com.android.internal.policy.impl.PhoneWindow $ DecorView.draw(PhoneWindow.java:2621)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13744)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.View.getDisplayList(View.java:13786)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.view.HardwareRenderer $ GlRenderer.buildDisplayList(HardwareRenderer.java:1411)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.HardwareRenderer $ GlRenderer.draw(HardwareRenderer.java:1359)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewRootImpl.draw(ViewRootImpl.java:2672)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2538)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2154)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1249)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6364)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.Choreographer $ CallbackRecord.run(Choreographer.java:791)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.view.Choreographer.doCallbacks(Choreographer.java:591)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.Choreographer.doFrame(Choreographer.java:561)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:777)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   android.os.Handler.handleCallback(Handler.java:730)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.os.Handler.dispatchMessage(Handler.java:92)03-31   20:45:44.131:E / AndroidRuntime(27445):at   android.os.Looper.loop(Looper.java:176)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   android.app.ActivityThread.main(ActivityThread.java:5419)03-31   20:45:44.131:E / AndroidRuntime(27445):at   java.lang.reflect.Method.invokeNative(Native Method)03-31   20:45:44.131:E / AndroidRuntime(27445):at   java.lang.reflect.Method.invoke(Method.java:525)03-31 20:45:44.131:   E / AndroidRuntime(27445):at   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1046)   03-31 20:45:44.131:E / AndroidRuntime(27445):at   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)03-31   20:45:44.131:E / AndroidRuntime(27445):at   dalvik.system.NativeStart.main(原生方法)

1 个答案:

答案 0 :(得分:5)

你应该研究一下onDraw()生命周期。

onDraw在开始时被调用,然后每次有“ something ”绘制时都会再次调用。如何告诉视图它有“某事”来绘制?通过调用“invalidate”。

因此,如果未加载积分,那么在onDraw 上您一开始就什么都不做

完成计算后,只需致电invalidate(),稍后将调用onDraw异步。到目前为止,在你的OnDraw中,你会发现你的计算已准备就绪,所以然后就是你画画的时候。

有点:

 boolean myCalculationsAreReady=false;

 Paint mPaint=new Paint(); // to draw text "loading" ... (new edit). You have to call mPaint.setColor(Color.WHITE) or any color you want, the default would be Black.

 public void onDraw(Canvas canvas) {

      if (myCalculationsAreReady) {

            drawMyStuff (canvas);

      } else {

            // You don't have your calculations yet , just ignore, or paint a message ...
            drawDataNotReady(canvas);

      }

 }

 private void drawMyStuff (Canvas c) {
         // here you have your calculations available
         // time to draw !
 }

 // to make this view totally independent, you can create yourself a progress indicator here.
 // you can also put a standard progressbar at the parent level and notify the parent when
 // to show / hide it. I like this approach, because it's more efficient (you save one view)
 // but obviously you can use any fancy view you like over this one.

 private void drawDataNotReady (Canvas c) {
         c.drawText (0, c.getHeight() / 2, "Please wait while data is loading ...", mPaint); 
 }

 private void do_my_heavy_calculations () {

         // do all your calculations. 
         .
         .
         .             
         // when you are done:

         myCalculationsAreReady=true;

         invalidate(); // this will call onDraw
 }

当你理解它是如何工作的,如果你的计算很重,你肯定想把它们从UI线程中取出来。你可以像你问的那样使用普通的线程,但是,调用“invalidate”的方式是不同的:

view.postInvalidate();

这用于使主UI线程外部的视图无效(即你的线程)。

同时检查AsyncTask作为帮助编写异步线程的类。