【问题标题】:AsyncTask progressdialog not showing, doInBackground blocks UIAsyncTask 进度对话框未显示,doInBackground 阻止 UI
【发布时间】:2014-03-26 17:29:44
【问题描述】:

我一直试图在检索数据时让进度对话框工作。

我使用此链接 Implement android splash screen while loading data 开始,但似乎无法正常工作。

到目前为止,它没有显示任何进度条,因为我认为功能 fillMyTickets 阻塞了 UI 线程,因此没有显示对话框。我不明白如何解决这个问题。通过阅读 Stackoverflow,我找到了解决方案,例如在 AsyncTask 中使用 onProgressUpdate 函数,但这不是我想要的。我所需要的只是一个等待对话框,当 HTTP 调用结束时会显示下载并消失。

exampleFragment.java

中的Asynctask函数
private ProgressDialog dialog;
private class PrefetchData extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
    super.onPreExecute();
    dialog = new ProgressDialog(getActivity());
    dialog.setMessage("Downloading..");
    dialog.setIndeterminate(true);
    dialog.setCancelable(true);
    dialog.show();
}

@Override
protected Void doInBackground(Void... arg0) {
    fillMyTickets();
    return null;
}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    dialog.dismiss();
}
exampleFragment.java 中的

fillMyTickets 函数

private void fillMyTickets() {
        HttpReader httpReader = new HttpReader();
        httpReader
                .setOnResultReadyListener(new HttpReader.OnResultReadyListener() {
                    @Override
                    public void resultReady(String result) {

                        JsonHelper jsonHelper = new JsonHelper();
                        tickets = jsonHelper.getTickets(result);
                    }
                });
        httpReader
                .execute(url);
    }

onAttach(Activity activity)执行AsyncTask的函数

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
     new PrefetchData().execute();
}

此外,当在 AsyncTask 的 onPostExecute 中评论 dialog.dismiss() 时,对话框确实会显示,但当然永远不会关闭。

【问题讨论】:

  • 你能展示一下你是如何执行任务的吗?
  • 确保你在 UI 线程上调用 new PrefetchData().execute()(也许在你的 onClick 处理程序之一中,然后你应该得到你想要的。
  • 它必须自动加载。

标签: java android android-asynctask


【解决方案1】:

您正在调用注册侦听器并下载一些数据的方法,但在下载数据之前,您将从doInBackground 返回并关闭对话框,因此您的对话框正在显示和隐藏。尝试修改您的代码并在完成下载后关闭对话框:

private ProgressDialog dialog;
private class PrefetchData extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
    super.onPreExecute();
    dialog = new ProgressDialog(getActivity());
    dialog.setMessage("Downloading..");
    dialog.setIndeterminate(true);
    dialog.setCancelable(true);
    dialog.show();
}

@Override
protected Void doInBackground(Void... arg0) {
    HttpReader httpReader = new HttpReader();
    httpReader.setOnResultReadyListener(new HttpReader.OnResultReadyListener() {
                @Override
                public void resultReady(String result) {
                    JsonHelper jsonHelper = new JsonHelper();
                    tickets = jsonHelper.getTickets(result);
                    //finished the download and we dismiss the dialog
                    dialog.dismiss();
                }
            });
    httpReader.execute(url);
    return null;
}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
}

希望对你有帮助!

【讨论】:

  • doInBackground(Void...arg0) 错误,“此方法必须返回 Void 类型的结果”
【解决方案2】:

虽然我建议您使用 Volley 库来执行异步网络请求(具有重试策略、内置线程池执行器的内容,以及您可以扩展和修改的一些其他美味的东西),但在我过去的项目中使用过带有进度对话框的异步任务,并且之前遇到过这个确切的问题。我处理它的方法是在你的类中编写一个回调接口,该接口扩展 AsyncTask 将在 postExecute() 上调用。

public class MyDataGrabber extends AsyncTask<Void,Void,Void> {

    public interface Callback {
        public void onComplete(String data);
    }
    public Callback callBack;
    public MyDataGrabber(Callback callback) { // Initialize the callback
        this.callBack = callback;
    }
   // on preExecute
   // on doInBackground
   public void onPostExecute(String data){
        this.callBack.onComplete(data);
   }
}

// So when you call your async task it will look like this

Dialog dialog;
//.... set up and show dialog etc.

new MyDataGrabber(new MyDataGrabber.Callback(){
    @Override
    public void onComplete(String data){
        // Handle data
        doDataHandling();
        // Dismiss dialog
        if(dialog.isShowing){
            dialog.dismiss();
        }
    }
}).execute(String url...other data etc);

虽然关于 AsyncTask 的缺点,Salauyou 是正确的,但它存在一些负面影响,取决于 android api 级别以及并发问题和异步任务仍在后台运行,即使您关闭了它,它也会并行或串行执行应用程序。通常,它需要您编写各种取消方法和弱引用才能正确处理。使用线程和处理程序也绝对是一个值得的解决方案。

【讨论】:

  • 此外,许多进度对话框可以在操作栏中使用 setSupportProgressBarIndeterminateVisibility(false|true) // appcompat version | 进行处理setProgressBarIndeterminateVisibility(false|true)
【解决方案3】:

好吧,所以我误读了这个问题....但是 doinbackground 不应该阻止任何这就是为什么它在后台。

不,这就是答案....对话框实际上不在 ui 上。只需从您的常规活动而不是异步任务中运行它。我只是像这样使用你的男女同校,而且很漂亮

public class MainActivity extends Activity {
    private ProgressDialog dialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         dialog = new ProgressDialog(this);
            dialog.setMessage("Downloading..");
            dialog.setIndeterminate(true);
            dialog.setCancelable(true);
            dialog.show();
        }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

所以基本上将对话框本身移出异步任务,并使用“this”作为上下文。如果您将访问权限从私有更改为公共,则从应用中的任何位置启动或终止它都没有问题

【讨论】:

  • 我不是在尝试制作启动画面,我只使用了指南的最后一部分。我试图在下载票证并将其放入列表视图时显示一个对话框。使用我上面的代码时,对话框也根本不显示。这就是为什么我认为 UI 被阻止的原因,因为对话框在 doInBackground 之前和之后被打开和关闭。
  • Dialog isUI Thread 上,正如它在onPreExecute() 中显示的那样确实UI Thread 上运行。
  • 是的,但 id dosnt 必须严格地说...我不是争论不休...只是说您可以通过将获取保留在异步中并将对话框移至主来实现您想要的活动,把它想象成一个花哨的吐司,你不需要对话的异步任务
  • 你说,“对话实际上不在 ui 上”,但现在,“是的,他的对话是”。无论如何,如果这样做,则不需要AsyncTask...只需使用Thread
  • 顺便说一句,这是一个相当漂亮的对话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多