更新

我的小陈列柜存放在Bitbucket上

https://bitbucket.org/solvapps/animationtest

我有一个带有 View 的 Activity 。 Contentview设置为此 View 。

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,它会定期刷新 View 。
但是invalidate()不会刷新 View 。
public class MovieTask extends AsyncTask<String, String, String> {

    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); }
您正在某个名为MovieTask的类中手动调用方法,因此您正在同一线程上运行代码。显然,这并非您的 Intent ,您打算在后台线程上运行计算代码。

启动AsyncTask的正确方法是使用 execute(Params...) :
public void startMovie() { MovieTask movieTask = new MovieTask(myView, this); movieTask.execute(""); }
现在您将获得理想的效果。

P.S.

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

setBall(int pos)类中声明MyBall方法:
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(); }
您将获得没有讨厌代码的相同动画。

10-05 21:01