如何在加载数据之前渲染视图

How to render a view before loading data

我开发了一个与云服务器通信的应用程序。现在我想在加载数据时添加一些反馈。例如,用户单击 "get data" 按钮加载数据,按钮文本应更改为 "loading"。并且当加载数据时,文本再次变为"get data"。

然而,第一次尝试没有成功,我做了一些研究,这是因为视图在任务完成之前不会呈现。 (我使用 AsyncTask 加载数据)。我在网上找到了一个解决方案,告诉我应该在 onPreExecute() 和 onPostExecute() 方法中渲染视图,所以我尝试了这种方法。嗯,也没用。

似乎有一个约束,强制渲染工作只在所有 AsyncTask 完成后才完成。

谁能赐教一下?困扰我好久了。

虽然我建议对云 API 操作进行 Retrofit,但如果您想使用 AsyncTask,那很好。我还建议使用 ProgressBar / Dialog 而不是只更新一些文本。

the view will not render until the task is finished

不清楚...

I found a solution online informs that I should render the view in the onPreExecute() and onPostExecute() method, so I tried the approach. Well, it does not work either

是的,那会起作用,所以你应该展示你尝试过的

it seems that there is a constraint that forces the rendering work to be done only after all the AsyncTask has finished

是的,有一个限制,您不能在 UI 线程之外更新 UI。这就是 onPreExecute 和 onPostExecute 存在的原因。


我可以保证这些方法有效。

public class ButtonActivity extends android.support.v7.app.AppCompatActivity implements View.OnClickListener {

    private Button button;
    private ProgressBar pg;

    @Override
    protected void onCreate(Bundle b) {
        super.onCreate(b);
        setContentView(...);

        button = (Button) findViewById(...);
        button.setOnClickListener(this);

        pg = (ProgressBar) findViewById(...);
        setLoading(false);
    }

    private void setLoading(boolean loading) {
        button.setText(loading ? "loading" : "get data");
        pg.setVisibility(loading ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onClick(View v) {
        new BackgroundTask().execute();
    }

    private class BackgroundTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setLoading(true);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                // some long operation
                Thread.sleep(3000);
            } catch (InterruptedException e) { }

            return null;
        }


        @Override
        public void onPostExecute(Void result) {
            setLoading(false);
        }
    }
}