我正在编写一个应用程序,我有一个自定义视图。在这个自定义视图中,我必须计算未确定点数的位置。点数取决于我从数据库中读取的内容(因此每个用户的内容都不同)。 所以,我的问题是,我怎样才能以一种好的方式解决这个问题呢?该应用程序的步骤如下:
问题是当我打开活动时会调用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(原生方法)
答案 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
作为帮助编写异步线程的类。