gressDialog在Android中的AsyncTask没有

gressDialog在Android中的AsyncTask没有

本文介绍了ProgressDialog在Android中的AsyncTask没有在正确的时间显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我得在什么基本的OData在我的Andr​​oid应用程序将这些长时间运行的服务器调用。呼叫的消费者使用 .execute()。获得()来等待来自网线的响应(我知道正确的方法是使整个事情异步和回调为主,但以任何方式没有这个数据的应用程序无法运行,并且完全重新构建它以这种方式工作似乎并没有提供任何好处)。

所以,我发现有很多片段在网上,其中使用 ProgressDialog 结合上preExecute() onPostExecute()如图所示,code样品下面可以用来显示一个进度对话框,而的AsyncTask 执行。我使用完全相同提供的样品,但会发生什么是呼叫启动时,它会等待网络交易,然后的非常的快速闪烁,会隐藏进度对话框。它可以坐整秒等待的事务,我知道一个事实,即它在等待在 doInBackground(),但该对话框就不会弹出直到非常最后,使其有效地无用的。

在下面的的DoEvents的code()位基本上是一个很短的睡眠。我已经试过,没有它,并似乎没有成为一个区别,但它似乎值得一试。

 类GetFromServerTask扩展的AsyncTask<弦乐,太虚,字符串>
    {
        私人上下文的背景下;
        私人ProgressDialog对话框;        公共GetFromServerTask(上下文CTX){
            上下文= CTX;
            对话框=新ProgressDialog(CTX);
        }        @覆盖
        在preExecute保护无效(){
            super.on preExecute();
            dialog.setMessage(正在加载...);
            dialog.show();
            的DoEvents();
        }        @覆盖
        保护字符串doInBackground(字符串... PARMS){
            如果(InOfflineMode)
                返回notdeserializable            字符串URL = PARMS [0];
            HttpURLConnection类的URLConnection = NULL;
            尝试{
                网址typedUrl =新的URL(网址);
                URLConnection的=(HttpURLConnection类)typedUrl.openConnection();                //添加授权令牌
                如果(InDebugMode){
                    urlConnection.addRequestProperty(的authToken的authToken);
                }其他{
                    urlConnection.addRequestProperty(授权,承载+的authToken);
                }
                urlConnection.addRequestProperty(接受,应用/ JSON);                的DoEvents();
                在的InputStream =新的BufferedInputStream(urlConnection.getInputStream());
                字节[]内容=新的字节[in.available()];                INT读取动作= 0;
                字符串strContents中=;
                而((读取动作= in.read(内容))!= - 1){
                    strContents的+ =新的String(内容,0,读取动作);
                    的DoEvents();
                }                如果(strContents.startsWith(< HTML>中))
                    回归错误:连接到服务时接收到意外HTML请确保您没有连接到需要身份验证的WIFI。                返回strContents的;
            }赶上(十六进制的UnknownHostException){
                返回错误:无法找到服务器地址请确保您连接到互联网,如果你只是改变了连接(即:开启或关闭WIFI)。这使花一分钟刷新;
            }
            赶上(例外前){
                串味精=错误:+ ex.getClass()的getName()+:+ ex.getMessage();
                Log.e(TE,味精);
                返回味精;
            } {最后
                如果(URLConnection的!= NULL)
                    urlConnection.disconnect();
            }
        }        @覆盖
        保护无效onPostExecute(字符串结果){
            super.onPostExecute(结果);
            如果(对话= NULL&放大器;!&安培; dialog.isShowing())
                dialog.dismiss();
            的DoEvents();
        }
    }

我也试过了稍微不同的版本,SO其他建议(如下图所示)使用相同的确切的结果:

 上preExecute保护无效(){
    对话框= ProgressDialog.show(背景下,,载入中...,真,假);
    super.on preExecute();
}

我也试着服用 ProgressDialog 出的的AsyncTask 一起,并将其显示外部任务,如下所示。在这种情况下,它甚至没有出现。

  ProgressDialog对话框= ProgressDialog.show(ServerAccessLayer.m_context,,载入中...,真,假);
字符串retVal的=新GetFromServerTask(ServerAccessLayer.m_context).execute(URL)获得();
dialog.dismiss();返回retVal的;


解决方案

好吧,你的问题是你的获得()。获得是一个阻塞调用。这意味着你不会回到事件循环(在调用Android框架的code 的onCreate 的onPause ,事件处理程序, onPostExecute 上preExecute 等),直到它返回后。如果不返回到事件循环,你永远不会进入绘图code,你就不会显示进度对话框。如果你想显示的对话框中,你需要重新构建您的应用程序实际使用异步任务。侧注意 - 如果你调用获得()一样,在​​你的UI线程,你的整个应用程序将冻结,并期待打破。这就是为什么他们迫使人们首先在UI线程不会做网络IO。

So I've got these long running server calls over what is basically OData going on in my Android application. The consumer of the calls uses .execute().get() to wait for the response from the network thread (I know the proper way is to make the whole thing asynchronous and callback-based, but the app cannot function in any way without this data, and completely rearchitecting it to work in that way doesn't seem to provide any benefits).

So I found many snippets online where using the ProgressDialog in combination with onPreExecute() and onPostExecute() as shown in the code sample below can be used to show a progress dialog while the AsyncTask executes. I'm using exactly the samples provided, but what happens is that the call starts, it waits for the network transaction, then very quickly flashes and hides the progress dialog. It can sit for whole seconds waiting on the transaction and I know for a fact that it's waiting in the doInBackground(), but the dialog just won't pop up until the very end, making it effectively useless.

In the code below the DoEvents() bit is basically just a very short sleep. I've tried with and without it and there doesn't seem to be a difference, but it seemed worth trying.

class GetFromServerTask extends AsyncTask<String, Void, String>
    {
        private Context context;
        private ProgressDialog dialog;

        public GetFromServerTask(Context ctx) {
            context = ctx;
            dialog = new ProgressDialog(ctx);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog.setMessage("Loading...");
            dialog.show();
            DoEvents();
        }

        @Override
        protected String doInBackground(String... parms) {
            if(InOfflineMode)
                return "notdeserializable";

            String url = parms[0];
            HttpURLConnection urlConnection = null;
            try {
                URL typedUrl = new URL(url);
                urlConnection = (HttpURLConnection) typedUrl.openConnection();

                //Add Authorization token
                if(InDebugMode) {
                    urlConnection.addRequestProperty("AuthToken", AuthToken);
                } else {
                    urlConnection.addRequestProperty("Authorization", "Bearer " + AuthToken);
                }
                urlConnection.addRequestProperty("Accept", "application/json");

                DoEvents();
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                byte[] contents = new byte[in.available()];

                int bytesRead = 0;
                String strContents = "";
                while((bytesRead = in.read(contents)) != -1){
                    strContents += new String(contents, 0, bytesRead);
                    DoEvents();
                }

                if(strContents.startsWith("<HTML>"))
                    return "Error: Received unexpected HTML when connecting to service.  Make sure you are not connected to a WIFI that requires authentication.";

                return strContents;
            } catch(UnknownHostException hex) {
                return "Error: Could not find server address.  Make sure you are connected to the internet.  If you just changed connections (ie: turning WIFI on or off) it make take a minute to refresh";
            }
            catch(Exception ex) {
                String msg = "Error: " + ex.getClass().getName() + ": " + ex.getMessage();
                Log.e("TE", msg);
                return msg;
            } finally {
                if(urlConnection != null)
                    urlConnection.disconnect();
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if(dialog != null && dialog.isShowing())
                dialog.dismiss();
            DoEvents();
        }
    }

I've also tried the slightly different version suggested elsewhere on SO (shown below) with the same exact results:

protected void onPreExecute() {
    dialog=ProgressDialog.show(context, "", "Loading...", true, false);
    super.onPreExecute();
}

I've also tried taking the ProgressDialog out of the AsyncTask all together and showing it "outside" the task, as shown below. In this case it doesn't even appear.

ProgressDialog dialog = ProgressDialog.show(ServerAccessLayer.m_context, "", "Loading...", true, false);
String retVal = new GetFromServerTask(ServerAccessLayer.m_context).execute(url).get();
dialog.dismiss();

return retVal;
解决方案

Ok, your problem is your .get(). .get is a blocking call. This means you won't return to the event loop (the code in the Android Framework that calls onCreate, onPause, event handlers, onPostExecute, onPreExecute, etc) until after it returns. If you don't return to the event loop, you won't ever go into the drawing code, and you won't display the progress dialog. If you want to show the dialog, you need to rearchitect your app to actually use the task asynchronously. Side note- if you're calling .get() like that on your UI thread, your entire app will freeze up and look broken. That's why they forced people to not do network IO on the UI thread in the first place.

这篇关于ProgressDialog在Android中的AsyncTask没有在正确的时间显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 18:22