AsyncTask:使视图无效不会生效

mcf*_*oft 8 java android android-animation android-asynctask android-view

更新

我的小橱窗存放在Bitbucket上

https://bitbucket.org/solvapps/animationtest

我有一个带有视图的Activity.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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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();
            }
        });

    }

}
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙吗?

azi*_*ian 7

了解如何启动AsyncTask:


    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("");
    }

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


PS

请不要使用该代码:您不需要启动后台线程来执行此类操作.作为替代方案考虑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();
    }

没有讨厌的代码你会得到相同的动画.