【问题标题】:AsyncTask is still blocking UI(UI not responding)AsyncTask 仍然阻塞 UI(UI 没有响应)
【发布时间】:2015-10-10 16:13:06
【问题描述】:

我有一个新闻应用程序,我可以在其中获取几个 XML 和 API 并立即插入数据库。我在获取/插入数据库过程中使用 AsyncTask。但是我仍然收到一个块(UI 没有响应)

for (int i = 0; i < urls.size(); i++) {
    MyAsyncTask myAsyncTask =  new MyAsyncTask(urls.get(i));
    myAsyncTask.execute();
}

AsyncTask 类:

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

    Url mUrl;
    public MyAsyncTask(Url url){
        this.mUrl = url;
    }


    @Override
    protected Void doInBackground(Void... params) {
        connect(mUrl.getUrl(),mUrl.getSourceName(),mUrl.getChoice(),mUrl.getId());
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        whenToInflate[mUrl.getId()] = true;
        mProgressState += 15;
        mProgress.setProgress(mProgressState);

        if (areAllTrue(whenToInflate)) {
            inflate(1907);
            Arrays.fill(whenToInflate, false);
        }
    }
}

连接方法:

private void connect(String url, final String sourceSite, final int sourceChoice, final int i) {


    stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {
                        if (sourceChoice == 14) {
                            database.insertFixtures(response, "FOOTBALL");
                        } else if (sourceChoice == 10 || sourceChoice == 20) {
                            database.insertNews(response, sourceChoice);
                        } else {
                            if (sourceChoice == 1) response = URLDecoder.decode(URLEncoder.encode(response, "iso8859-1"), "UTF-8");
                            database.insertNewsXML(response, sourceSite, sourceChoice);
                        }


                    } catch (IllegalStateException | IllegalArgumentException | UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();

        }
    });

    VolleySingleton.getInstance(getActivity()).addToRequestQueue(stringRequest);
}

VolleySingleton 类:

public class VolleySingleton {
    private static VolleySingleton instance;
    private static VolleySingleton ourInstance = new VolleySingleton();
    private RequestQueue requestQueue;

    private VolleySingleton() {
    }

    private VolleySingleton(Context context) {
        requestQueue = Volley.newRequestQueue(context);
    }

    public static VolleySingleton getInstance() {
        return ourInstance;
    }

    public static VolleySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new VolleySingleton(context);
        }
        return instance;
    }

    public RequestQueue getRequestQueue() {
        return requestQueue;
    }


    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag("App");
        getRequestQueue().add(req);
    }
}

【问题讨论】:

  • 请向我们展示StringRequest的课程以及您如何管理VolleySingleton
  • 添加了 VolleySingleton 并且 StringRequest 是一个使用 Android Volley Libarary(mcxiaoke.volley:library) 的对象

标签: android android-asynctask android-volley


【解决方案1】:

那是因为您正在更新 mProgress 的进度。所以这就是它给出错误的原因。在 onProgressUpdate 方法 AsyncTask 中更新进度。

【讨论】:

  • 检查我的更新,我已修复,但 UI 仍然被阻止,似乎不是问题
  • 好的。但是 onPostExecute 只会在 doInBackground 之后被调用一次。
  • 是的,我知道,我检查我的布尔数组是否全部为真,如果是,那么我会在所有网站都被提取并插入数据库时​​膨胀数据
  • @busted13 我怀疑 Hardik 是对的:在 postExecute 中充气使您的 UI 仅在执行完成后才可用。
  • 那么我应该在何时/何地扩充数据?我在 doinbackground 内部尝试过,它在 Connect 方法内部,现在它在 OnPostExecute 方法内部,结果仍然相同
【解决方案2】:

您的项目在 AsyncTask 中使用 Volley 看起来很奇怪,我以前从未做过这样的事情。

我建议您阅读我对以下问题的回答以供参考:

Android Volley: Static vs Object

POST Request Json file passing String and wait for the response Volley

您会发现我在其中使用了Interface,如下所示:

public interface VolleyResponseListener {
    void onError(String message);

    void onResponse(Object response);
}

然后我将VolleyResponseListener 作为方法的参数传递,在您的情况下是connect 方法。

回到你的问题,IMO,你只需要在你的主线程中调用你的 Volley 请求(我的意思是 stringRequest = new StringRequest... 直接在 onCreate 内部调用)

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多