AsyncTask:使视图无效不会生效

更新

我的小橱窗存放在Bitbucket上

https://bitbucket.org/solvapps/animationtest

我有一个带有视图的活动。 Contentview设置为此视图。

 public class MainActivity extends AppCompatActivity { private MyView myView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myView = new MyView(this); setContentView(myView); startMovie(); } public void startMovie(){ MovieTask movieTask = new MovieTask(myView, this); movieTask.doInBackground(null); } } 

MovieTask是一个Asynctask并定期刷新视图。 但invalidate()不刷新视图。

 public class MovieTask extends AsyncTask { MyView drawingView; MainActivity mainActivity; public MovieTask(MyView view, MainActivity mainActivity){ this.mainActivity = mainActivity; this.drawingView =view; } @Override protected String doInBackground(String... strings) { for(int i=20;i<100;i++){ drawingView.myBall.goTo(i,i); publishProgress(); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } } return null; } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); mainActivity.runOnUiThread(new Runnable() { @Override public void run() { Log.v("DEBUG_DRAW","in onProgressUpdate()"); drawingView.invalidate(); } }); } } 

有人可以帮忙吗?

了解如何启动AsyncTask

public void startMovie() { MovieTask movieTask = new MovieTask(myView, this); movieTask.doInBackground(null); }
public void startMovie() { MovieTask movieTask = new MovieTask(myView, this); movieTask.doInBackground(null); } 

您正在手动调用名为MovieTask某个类中的方法,因此您在同一个线程上运行代码。 显然,这不是你的意图,你打算在后台线程上运行计算代码。

正确启动AsyncTask是使用execute(Params...)

public void startMovie() { MovieTask movieTask = new MovieTask(myView, this); movieTask.execute(""); }
public void startMovie() { MovieTask movieTask = new MovieTask(myView, this); movieTask.execute(""); } 

现在你将获得所需的效果。


PS

请不要使用该代码:您不需要启动后台线程来执行此类操作。 作为替代方案,请考虑Animators API 。

MyBall类中声明setBall(int pos)方法:

public class MyView extends View { ... public void setBall(int pos) { myBall.setX(pos); myBall.setY(pos); invalidate(); } }
public class MyView extends View { ... public void setBall(int pos) { myBall.setX(pos); myBall.setY(pos); invalidate(); } } 

然后将startMovie()更改为以下内容:

public void startMovie() { // "ball" means, that Animators API will search for `public setBall(int)` method inside MyView.java and call that method ObjectAnimator ball = ObjectAnimator.ofInt(myView, "ball", 20, 100); ball.setDuration(1000); ball.start(); }
public void startMovie() { // "ball" means, that Animators API will search for `public setBall(int)` method inside MyView.java and call that method ObjectAnimator ball = ObjectAnimator.ofInt(myView, "ball", 20, 100); ball.setDuration(1000); ball.start(); } 

没有讨厌的代码你会得到相同的animation。

有两种可能的情况,首先如文件中所述 :

void invalidate()使整个视图无效。 如果视图可见,将在某个时间点调用onDraw(android.graphics.Canvas)。

因此,尝试在onResume运行代码, View有可能尚未显示。

其次, View#invalidate告诉系统在主UI线程空闲时重绘视图。 也就是说,调用invalidate会在所有其他即时工作完成后重新调度您的视图。

如果您希望定期更新视图,请使用Handler#postDelay或在单独的线程中运行它,并使用View#postInvalidate更新View并触发对onDraw的调用。