How to use ProgressDialog to show JSON parsing pro

2019-09-09 07:01发布

问题:

I want to show progress of some JSON parsing using with progress bar. I've never used it and found some examples in the Internet. So, I try to realize it but application crashes when parsing starts. Here is code:

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();
    }
}
}

If i don't use ProgressDialog (just comment or delete dialog code) application works correctly. How can I fix it?

回答1:

Without any logcat it's difficult to help, but it seems that your ctx is null so

dialog = new ProgressDialog(ctx);

the dialog can't be created.

Try to add constructor to the AsyncTask and pass the context here, something like:

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

To start the task:

new ParseTask(this).execute();


回答2:

Well, I suppose this can be done in much easier and modern way.

  1. use GSON to parse Your JSON
  2. consider using Retrofit for REST

Now step by step:

  1. add dependencies to Your gradle file:

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

this will let U use retrofit lib 2. Create retrofit serverAPI interface

    public interface InternalServerAPI {

    @GET("users/statistics")
    Call<Example> healthcheckEndPoint(Params... params);
    }
  1. Create a corresponding to Your JSON object (POJO). U can use this online http://www.jsonschema2pojo.org. For instance U`ve got JSON like this:

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

    }

U`ll obtain two model classes like this:

    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. Now build the retrofit object:

    Retrofit mRetrofit = new Retrofit.Builder()
                            .addConverterFactory(GsonConverterFactory.create())
                            .baseUrl(Constants.BASE_INTERNAL_SERVER_ADDRESS)
                            .build();
    
  2. And refer to correspondin endPoint, but first call your progress dialog:

    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();
    }
                                });
    

Of course all of this should be done in some MVP way, but it is not a subject now.