Android Async任务从Web获取json字符串

时间:2014-03-06 14:33:06

标签: android multithreading asynchronous

我的类从web读取一个json字符串,并使用收集的字符串填充一个hashmap。 我正在使用AsyncTask通过progressdialog读取数据,以让设备“正在工作”。 这是我的班级:

class ArmoryAsyncProgress extends AsyncTask<String, Void, Void> {

    private Context         mContext;
    private ProgressDialog  mProgressDialog;
    private String tempRes;

    public ArmoryAsyncProgress(Context mContext)
    {
        this.mContext = mContext;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = ProgressDialog.show(mContext, "Carica!", "Gira!");
    }

    @SuppressLint("NewApi")
    @Override
    protected String doInBackground(String... sUrl) {
        try {
            URL json = new URL(Utility.BASE_URL + "api.php?action=armory&guid="+pGuid);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                            json.openStream()));
            String input;
            while((input = in.readLine()) != null)
                Result += input;

            json = new URL(Utility.BASE_URL + "api.php?action=armory_stats&guid="+pGuid);
            in = new BufferedReader(
                    new InputStreamReader(
                            json.openStream()));
            input = "";
            String ret = "";
            while((input = in.readLine()) != null)
                ret += input;

            tempRes = Result + "Ø" + ret;
            String debug = tempRes;
        }
        catch(MalformedURLException e){
            e.printStackTrace();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }

        ActivityArmory.result = tempRes;
        return null;
    }

    protected void onPostExecute(String result) {

        /*********************************************************************************/
        try
        {
            String ret;
            while(result == null)
                Thread.sleep(500);
            String[] temp = result.split("Ø");
            pJSON = temp[0];
            ret = temp[1];

            JSONObject pl = new JSONObject(ret);
            stats.put("Level", pl.getString("level"));
            stats.put("Classe", pl.getString("class"));
            stats.put("Name", pl.getString("pname"));
            stats.put("Race", pl.getString("race"));

            stats.put("health", pl.getString("health"));
            stats.put("power", pl.getString("power1"));
            stats.put("gname", pl.getString("gname"));
            stats.put("pnote", pl.getString("pnote"));
            stats.put("offnote", pl.getString("offnote"));
            stats.put("rname", pl.getString("rname"));

            JSONArray jObject = new JSONArray(pJSON);

            for (int i = 0; i < jObject.length(); i++) {
                JSONObject item = jObject.getJSONObject(i);
                ArmoryElement i1 = new ArmoryElement(
                        "http://wow.zamimg.com/images/wow/icons/large/" + item.getString("itemIMG") + ".jpg",
                        item.getInt("itemID"), item.getInt("quality"));

                el.put(item.getString("itemType"), i1);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    /****************************************************************/

        mProgressDialog.dismiss();
    }
}

这是对班级的调用:

new ArmoryAsyncProgress().execute(pGuid+"");

在“执行”方法调用之后,我调用另一个函数,用于格式化和显示从web获取的数据。 我的问题是没有显示在Async类中声明的progressDialog,并且在执行完成之前调用execute之后调用的函数(使用一些Log我发现在doInBackground完成之前显示第二个函数中的日志)

我也尝试了.get mothod,它冻结了主线程并阻止了函数被调用,但我无法显示progressdialog。

提前致谢

4 个答案:

答案 0 :(得分:1)

  

在执行完成之前调用execute之后调用的函数

这是正常的,因为AsyncTasks是异步的,这意味着它们将在后台运行并允许其他代码继续运行。要解决这个问题,

  1. 如果任务是Activity的内部类,您可以调用 在onPostExecute()

  2. 完成后要运行的功能
  3. 如果不是,那么您可以使用interface来提供回调 一旦完成,就到ActivitySee this answer for an example on interface

  4. 为什么ProgressDialog没有显示,我不太确定,但您可以从Thread.sleep()删除onPostExecute(),因为这将使您的主线程处于睡眠状态。我认为唯一需要onPostExecute()的是mProgressDialog.dismiss()。其余的可以在doInBackground()中完成。

    此外,您使用.get()是正确的,它会冻结您的UI Thread

答案 1 :(得分:1)

PostExecute()不能执行大型操作,在doInBackground中使用像json解析这样繁重的操作。要显示UI,即在textview或listview中显示,请使用PostExecute()

答案 2 :(得分:0)

不好的部分是:

    protected void onPostExecute(String result) {

    /*********************************************************************************/
    try
    {
        String ret;
        while(result == null)
            Thread.sleep(500);

因为它在UI线程中运行并且会与严格模式冲突。

    protected void onPostExecute(String result) {
if(result!=null){
    /*********************************************************************************/
    try
    {
        String ret;

        String[] temp = result.split("Ø");
        pJSON = temp[0];
        ret = temp[1];

        JSONObject pl = new JSONObject(ret);
        stats.put("Level", pl.getString("level"));
        stats.put("Classe", pl.getString("class"));
        stats.put("Name", pl.getString("pname"));
        stats.put("Race", pl.getString("race"));

        stats.put("health", pl.getString("health"));
        stats.put("power", pl.getString("power1"));
        stats.put("gname", pl.getString("gname"));
        stats.put("pnote", pl.getString("pnote"));
        stats.put("offnote", pl.getString("offnote"));
        stats.put("rname", pl.getString("rname"));

        JSONArray jObject = new JSONArray(pJSON);

        for (int i = 0; i < jObject.length(); i++) {
            JSONObject item = jObject.getJSONObject(i);
            ArmoryElement i1 = new ArmoryElement(
                    "http://wow.zamimg.com/images/wow/icons/large/" + item.getString("itemIMG") + ".jpg",
                    item.getInt("itemID"), item.getInt("quality"));

            el.put(item.getString("itemType"), i1);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
/****************************************************************/
}
    mProgressDialog.dismiss();
}
偶数bader部分是:

 return null;
你的doInBackground方法中的

但是,这应该有效:

class ArmoryAsyncProgress extends AsyncTask<String, Void, Void> {

    private Context         mContext;
    private ProgressDialog  mProgressDialog;
    private String tempRes;

    public ArmoryAsyncProgress(Context mContext)
    {
        this.mContext = mContext;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = ProgressDialog.show(mContext, "Carica!", "Gira!");
    }

    @SuppressLint("NewApi")
    @Override
    protected String doInBackground(String... sUrl) {
        try {
            URL json = new URL(Utility.BASE_URL + "api.php?action=armory&guid="+pGuid);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                            json.openStream()));
            String input;
            while((input = in.readLine()) != null){
                Result += input;
            }
            json = new URL(Utility.BASE_URL + "api.php?action=armory_stats&guid="+pGuid);
            in = new BufferedReader(
                    new InputStreamReader(
                            json.openStream()));
            input = "";
            String ret = "";
            while((input = in.readLine()) != null){
                ret += input;
            }
            tempRes = Result + "Ø" + ret;
            String debug = tempRes;
        }
        catch(MalformedURLException e){
            e.printStackTrace();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }

        ActivityArmory.result = tempRes;
        return tempRes;
    }

    protected void onPostExecute(String result) {
        if(result!=null)
        /*********************************************************************************/
        try
        {
            String ret;
            String[] temp = result.split("Ø");
            pJSON = temp[0];
            ret = temp[1];

            JSONObject pl = new JSONObject(ret);
            stats.put("Level", pl.getString("level"));
            stats.put("Classe", pl.getString("class"));
            stats.put("Name", pl.getString("pname"));
            stats.put("Race", pl.getString("race"));

            stats.put("health", pl.getString("health"));
            stats.put("power", pl.getString("power1"));
            stats.put("gname", pl.getString("gname"));
            stats.put("pnote", pl.getString("pnote"));
            stats.put("offnote", pl.getString("offnote"));
            stats.put("rname", pl.getString("rname"));

            JSONArray jObject = new JSONArray(pJSON);

            for (int i = 0; i < jObject.length(); i++) {
                JSONObject item = jObject.getJSONObject(i);
                ArmoryElement i1 = new ArmoryElement(
                        "http://wow.zamimg.com/images/wow/icons/large/" + item.getString("itemIMG") + ".jpg",
                        item.getInt("itemID"), item.getInt("quality"));

                el.put(item.getString("itemType"), i1);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    /****************************************************************/
    }
        mProgressDialog.dismiss();
    }
}

答案 3 :(得分:0)

你必须改变doInBackground的返回值,因为这个值在onPostExecute中使用