如何使用ProgressDialog显示JSON解析进度?

How to use ProgressDialog to show JSON parsing progress?

我想用进度条显示一些 JSON 解析的进度。我从来没有使用过它并在互联网上找到了一些例子。因此,我尝试实现它,但在解析开始时应用程序崩溃了。这是代码:

public class Parser extends Activity {

public static String w_type1 = "news";
public static String w_type2 = "events_put";
public ListView lv;
ArrayList<Widget> data = new ArrayList<Widget>();
WidgetAdapter wid_adptr = new WidgetAdapter(this, data);

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_parser);


    lv = (ListView) this.findViewById(R.id.list);
    lv.setAdapter(wid_adptr);
    new ParseTask().execute();

}

private class ParseTask extends AsyncTask<Void, Void, String> {
    HttpURLConnection urlConnection = null;
    BufferedReader reader = null;
    String resultJson = "";

    public ProgressDialog dialog;
    Context ctx;

    protected void onPreExecute() {
        dialog = new ProgressDialog(ctx);
        dialog.setMessage("Pasring...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.show();
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            URL url = new URL("http://api.pandem.pro/healthcheck/w/");

            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();

            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }

            resultJson = buffer.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultJson;
    }

    @Override
    protected void onPostExecute(String strJson) {
        super.onPostExecute(strJson);


        JSONObject dataJsonObj = null;

        try {
            dataJsonObj = new JSONObject(strJson);
            JSONArray widgets = dataJsonObj.getJSONArray("widgets");

            for (int i = 0; i < widgets.length(); i++) {
                JSONObject widget = widgets.getJSONObject(i);

                String wType = widget.getString("type");

                if (wType.equals(w_type1) || wType.equals(w_type2)) {

                    String title = widget.getString("title");
                    String desc = widget.getString("desc");
                    String img_url = "";
                    if (widget.has("img")) {
                        JSONObject img = widget.getJSONObject("img");
                        img_url = img.getString("url");
                    }
                    data.add(new Widget(wType, title, desc, img_url));
                    //wid_adptr.notifyDataSetChanged();
                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        dialog.dismiss();
    }
}
}

如果我不使用 ProgressDialog(只是注释或删除对话框代码)应用程序可以正常工作。我该如何解决?

没有任何 logcat 很难提供帮助,但您的 ctx 似乎是空的,所以

dialog = new ProgressDialog(ctx);

无法创建对话框。

尝试将构造函数添加到 AsyncTask 并在此处传递上下文,例如:

private class ParseTask extends AsyncTask<Void, Void, String> {
...
    public ParseTask(Context ctx) {
        this.ctx = ctx;
    }
...
}

开始任务:

new ParseTask(this).execute();

嗯,我想这可以用更简单和现代的方式完成。

  1. 使用 GSON 解析你的 JSON
  2. 考虑使用 Retrofit for REST

现在一步步来:

  1. 将依赖项添加到您的 gradle 文件:

    compile "com.squareup.retrofit2:retrofit:$retrofitVersion"
    compile "com.squareup.retrofit2:converter-gson:$retrofitVersion"
    

这会让你使用改造库 2.创建改造serverAPI接口

    public interface InternalServerAPI {

    @GET("users/statistics")
    Call<Example> healthcheckEndPoint(Params... params);
    }
  1. 创建一个对应于你的JSON对象(PO​​JO)。你可以在线使用这个 http://www.jsonschema2pojo.org。例如你有这样的JSON:

    {
      "date":"1234343555",
      "widgets": [
        {
          "title":"title1",
          "desc":"desc1"
        },
        {
          "title":"title2",
          "desc":"desc2"
        },
        ...
      ]  
    

    }

您将获得两个模型 类,如下所示:

    public class Example {

    @SerializedName("date")
    @Expose
    private String date;
    @SerializedName("widgets")
    @Expose
    private List<Widget> widgets = new ArrayList<Widget>();

    /**
    * 
    * @return
    * The date
    */
    public String getDate() {
    return date;
    }

    /**
    * 
    * @param date
    * The date
    */
    public void setDate(String date) {
    this.date = date;
    }

    /**
    * 
    * @return
    * The widgets
    */
    public List<Widget> getWidgets() {
    return widgets;
    }

    /**
    * 
    * @param widgets
    * The widgets
    */
    public void setWidgets(List<Widget> widgets) {
    this.widgets = widgets;
    }

    }
    -----------------------------------com.example.Widget.java-----------------------------------

    package com.example;

    import javax.annotation.Generated;
    import com.google.gson.annotations.Expose;
    import com.google.gson.annotations.SerializedName;

    @Generated("org.jsonschema2pojo")
    public class Widget {

    @SerializedName("title")
    @Expose
    private String title;
    @SerializedName("desc")
    @Expose
    private String desc;

    /**
    * 
    * @return
    * The title
    */
    public String getTitle() {
    return title;
    }

    /**
    * 
    * @param title
    * The title
    */
    public void setTitle(String title) {
    this.title = title;
    }

    /**
    * 
    * @return
    * The desc
    */

public String getDesc() {
return desc;
}

/**
* 
* @param desc
* The desc
*/
public void setDesc(String desc) {
this.desc = desc;
}

}
  1. 现在构建改造对象:

    Retrofit mRetrofit = new Retrofit.Builder()
                            .addConverterFactory(GsonConverterFactory.create())
                            .baseUrl(Constants.BASE_INTERNAL_SERVER_ADDRESS)
                            .build();
    
  2. 并参考相应的端点,但首先调用您的进度对话框:

    dialog = new ProgressDialog(Parser.this);
            dialog.setMessage("Pasring...");
            dialog.setIndeterminate(true);
            dialog.setCancelable(true);
            dialog.show();
    
    Call<Example> fetchWidgets = mRetrofit.create(InternalServerAPI.class).healthcheckEndPoint(Params);
    fetchWidgets.enqueue(new Callback<Example>() {
      @Override
      public void onResponse(Call<Example> call, Response<Example> response) {
    //here response is your model object and U can refer to its fields
    ArrayList<Widget> data = response.getWidgets();
    ...
    //update adapter
    ...
    //and now U can dismiss your dialog
    dialog.dismiss();
    }
    
     @Override
     public void onFailure(Call<Example> call, Throwable t) {
    //here U can handle connection errors
    //and also dismiss dialog
    dialog.dismiss();
    }
                                });
    

当然,所有这些都应该以某种 MVP 方式完成,但现在不是主题。