简体   繁体   中英

Json response is very slow android

I'm writing an Android application which will occasionally need to download a json string of around 1MB and containing around 1000 elements, and parse each of these into an SQLite database, which I use to populate a ListActivity.

Even though the downloading and parsing isn't something that needs to be done on every interaction with the app (only on first run or when the user chooses to refresh the data), I'm still concerned that the parsing part is taking too long, at around two to three minutes - it seems like an eternity in phone app terms!

I am using this code... :-

            public class CustomerAsyncTask extends AsyncTask<String, Integer, String> {
            private Context context;
            private String url_string;
            private String usedMethod;
            private String identifier;
            List<NameValuePair> parameter;
            private boolean runInBackground;
            AsynTaskListener listener;
            private Bitmap bm = null;

            public ProgressDialog pDialog;
            public String entityUtil;
            int index = 0;
            public static int retry = 0;

            private String jsonString = "";

            private String DialogString = "";

            // use for AsyncTask web services-----------------
            public CustomerAsyncTask(Context ctx, String url, String usedMethod,
                    String identifier, boolean runInBackground, String DialogString,
                    List<NameValuePair> parameter, AsynTaskListener callack) {
                this.context = ctx;
                this.url_string = url;
                this.usedMethod = usedMethod;
                this.identifier = identifier;
                this.parameter = parameter;
                this.runInBackground = runInBackground;
                this.listener = callack;
                this.DialogString = DialogString;
            }

            public CustomerAsyncTask(Context ctx, String url, String usedMethod,
                    String identifier, boolean runInBackground,
                    List<NameValuePair> parameter, AsynTaskListener callack, Bitmap bm) {
                this.context = ctx;
                this.url_string = url;
                this.usedMethod = usedMethod;
                this.identifier = identifier;
                this.parameter = parameter;
                this.runInBackground = runInBackground;
                this.listener = callack;
                this.bm = bm;

            }

            @Override
            protected void onPreExecute() {
                // TODO Auto-generated method stub
                super.onPreExecute();
                if (runInBackground)
                    initProgressDialog(DialogString);
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                // TODO Auto-generated method stub
                super.onProgressUpdate(values);
            }

            @SuppressWarnings("deprecation")
            @Override
            protected String doInBackground(String... params) {
                HttpParams httpParameters = new BasicHttpParams();
                int timeoutConnection = 10000; // mili second
                HttpConnectionParams.setConnectionTimeout(httpParameters,
                        timeoutConnection);
                int timeoutSocket = 10000;
                HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
                DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
                try {
                    HttpResponse response = null;
                    if (usedMethod.equals(GlobalConst.POST)) {
                        HttpPost httppost = new HttpPost(this.url_string);
                        httppost.setHeader("Content-Type",
                                "application/x-www-form-urlencoded");
                        // Customer Login MObile
                        if (identifier.equals("Customer_Login")) {
                            if (params.length > 0) {
                                parameter = new ArrayList<NameValuePair>();
                                parameter.add(new BasicNameValuePair("cus_mob",
                                        params[0]));
                            }
                            httppost.setEntity(new UrlEncodedFormEntity(parameter));

                            // Customer Verify Code
                        } else if (identifier.equals("Customer_mob_verify")) {
                            if (params.length > 0) {
                                parameter = new ArrayList<NameValuePair>();
                                parameter.add(new BasicNameValuePair("cus_verify",
                                        params[0]));
                                parameter.add(new BasicNameValuePair("cus_mobile",
                                        params[1]));
                            }
                            httppost.setEntity(new UrlEncodedFormEntity(parameter));
                        } else if (identifier.equals("Dashboard")) {
                            if (params.length > 0) {
                                parameter = new ArrayList<NameValuePair>();
                                parameter.add(new BasicNameValuePair("cus_id",
                                        params[0]));
                            }
                            httppost.setEntity(new UrlEncodedFormEntity(parameter));
                        }
                        response = (HttpResponse) httpClient.execute(httppost);

                    } else if (usedMethod.equals(GlobalConst.GET)) {

                        HttpGet httpput = new HttpGet(this.url_string);
                        httpput.setHeader("Content-Type",
                                "application/x-www-form-urlencoded");
                        response = (HttpResponse) httpClient.execute(httpput);
                    }

                    // Buffer Reader------------------------
                    InputStream inputStream = null;
                    String result = null;
                    try {
                        HttpEntity entity1 = response.getEntity();
                        inputStream = entity1.getContent();
                        BufferedReader reader = new BufferedReader(
                                new InputStreamReader(inputStream, "UTF-8"), 8);
                        StringBuilder sb = new StringBuilder();
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                        }
                        result = sb.toString();
                    } catch (Exception e) {
                    } finally {
                        try {
                            if (inputStream != null)
                                inputStream.close();
                        } catch (Exception squish) {
                        }
                    }
                    jsonString = result;
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                    return AsyncResultConst.CONNEERROR;
                } catch (IOException e) {
                    e.printStackTrace();
                    return AsyncResultConst.CONNEERROR;
                } catch (Exception e1) {
                    e1.printStackTrace();
                    return AsyncResultConst.EXCEPTION;
                } finally {
                    httpClient.getConnectionManager().shutdown();
                }
                return AsyncResultConst.SUCCESS;
            }

            @Override
            protected void onPostExecute(String result) {
                // TODO Auto-generated method stub
                if (runInBackground)
                    pDialog.dismiss();
                if (result.equals(AsyncResultConst.SUCCESS)) {
                    listener.onRecieveResult(identifier, jsonString);
                } else if (result.equals(AsyncResultConst.PARSINGERROR)) {
                    // showAlertMessage(context, "Error", "Parsing Error", null);
                    listener.onRecieveException(identifier, result);
                } else {
                    if (retry < 0) {
                        retry++;
                        new CustomerAsyncTask(context, url_string, usedMethod,
                                identifier, runInBackground, DialogString, parameter,
                                listener).execute("");
                    } else {
                        // showAlertMessage(context, "Error", "Connection Error", null);
                        listener.onRecieveException(identifier, result);
                    }
                }
                super.onPostExecute(result);
            }

            private void initProgressDialog(String loadingText) {
                pDialog = new ProgressDialog(this.context);
                pDialog.setMessage(loadingText);
                pDialog.setCancelable(false);
                pDialog.show();
            }
        }

Don't use Async-task in such case, use native java thread here.

 new Thread(new Runnable() {
        public void run() {

             // Do your work .....

        }
    }).start();  

When need to update UI. Yes! Android won't allow you to do that. so... solution is: USE Handler for that :)

 Handler handler = new Handler(); 

 handler.post(new Runnable() {
      @Override
      public void run() {

           // Do Update your UI     

       }    
 });

Use AsyncTask for:

  1. Simple network operations which do not require downloading a lot of
  2. data Disk-bound tasks that might take more than a few milliseconds

Use Java threads for:

  1. Network operations which involve moderate to large amounts of data (either uploading or downloading)
  2. High-CPU tasks which need to be run in the background
  3. Any task where you want to control the CPU usage relative to the GUI thread

Try to use Jackson Library to manage your JSON. It is really efficient. You can find it here : http://mvnrepository.com/artifact/org.codehaus.jackson/jackson-jaxrs

I am using it for a 400KB file is less than 1 second.

If you want a tuto this one looks good http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/

您也可以使用Google的GSON。

This is how is read JSON into my listview in my app. The result is processed to my app in an average of 3 seconds on Wi-Fi and 5 seconds on 3G:

public class CoreTeamFragment extends ListFragment { ArrayList> membersList; private String url_all_leaders = //URL goes here private ProgressDialog pDialog;

JSONParser jParser = new JSONParser();

// JSON Node names
private static final String CONNECTION_STATUS = "success";
private static final String TABLE_TEAM = "CoreTeam";
private static final String pid = "pid";
private static final String COL_NAME = "CoreTeam_Name";
private static final String COL_DESC = "CoreTeam_Desc";
private static final String COL_PIC = "CoreTeam_Picture";

JSONArray CoreTeam = null;

public static final String ARG_SECTION_NUMBER = "section_number";

public CoreTeamFragment() {
}

public void onStart() {
    super.onStart();

    membersList = new ArrayList<HashMap<String, String>>();
    new LoadAllMembers().execute();

    // selecting single ListView item
    ListView lv = getListView();

    // Lauching the Event details screen on selecting a single event
    lv.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            // getting values from selected ListItem
            String ID = ((TextView) view.findViewById(R.id.leader_id))
                    .getText().toString();

            Intent intent = new Intent(view.getContext(),
                    CoreTeamDetails.class);
            intent.putExtra(pid, ID);
            view.getContext().startActivity(intent);
        }
    });
}

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_coreteam,
            container, false);

    return rootView;
}

class LoadAllMembers extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Just a moment...");
        pDialog.setIndeterminate(true);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    protected String doInBackground(String... args) {
        // Building Parameters
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        // getting JSON string from URL
        JSONObject json = jParser.makeHttpRequest(url_all_leaders,
                "GET", params);

        try {
            // Checking for SUCCESS TAG
            int success = json.getInt(CONNECTION_STATUS);

            if (success == 1) {
                // products found
                // Getting Array of Products
                CoreTeam = json.getJSONArray(TABLE_TEAM);
                // looping through All Contacts
                for (int i = 0; i < CoreTeam.length(); i++) {
                    JSONObject ct = CoreTeam.getJSONObject(i);

                    // Storing each json item in variable
                    String id = ct.getString(pid);
                    String name = ct.getString(COL_NAME);
                    String desc = ct.getString(COL_DESC);
                    String pic = ct.getString(COL_PIC);

                    // creating new HashMap
                    HashMap<String, String> map = new HashMap<String, String>();

                    // adding each child node to HashMap key => value
                    map.put(pid, id);
                    map.put(COL_NAME, name);
                    map.put(COL_DESC, desc);
                    map.put(COL_PIC, pic);

                    // adding HashList to ArrayList
                    membersList.add(map);

                }
            } else {
                // Options are not available or server is down.
                // Dismiss the loading dialog and display an alert
                // onPostExecute
                pDialog.dismiss();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    protected void onPostExecute(String file_url) {
        // dismiss the dialog after getting all products
        pDialog.dismiss();
        // updating UI from Background Thread
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                ListAdapter adapter = new SimpleAdapter(
                        getActivity(),
                        membersList,
                        R.layout.coreteam_item,
                        new String[] { pid, COL_NAME, COL_DESC, COL_PIC },
                        new int[] { R.id.leader_id, R.id.leaderName,
                                R.id.photo });
                setListAdapter(adapter);
            }
        });
    }
}

}

Use Volley or Retrofit lib.

Those lib are increasing the speed.

Volley:

JsonObjectRequest channels = new JsonObjectRequest(Method.POST,
                Constants.getaccountstatement + Constants.key, statement_object,
                new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject arg0) { 
}, new Response.ErrorListener()
        {
            @Override
            public void onErrorResponse(VolleyError e) {
                Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM