I was just wondering if my code is ok in terms of downloading. My app needs a lot of data from a database so quick download times are crucial. The download time is ok but I think it can be programmed more efficient. Can you have a look at this? This class downloads many different companies and when downloaded they are put in a HashMap corresponding to their category. When finished downloading this class return a HashMap which contains multiple Hashmaps(categories) and in these Hashmaps the downloaded data. Dont mind the actual workflow but please concentrate on the way this class downloads data. Is there a way to do this faster?
public class CompanyDAO {
private static Controller delegate;
private static String companyUrl = "http:// URL HERE";
private Map<Object, Object> companyMap = new HashMap<Object, Object>();
private Map<String, Integer> pinMap = new HashMap<String, Integer>();
public CompanyDAO (Controller _delegate, Map<String, Integer> map) {
delegate = _delegate; //reference to controller
pinMap = map;
}
public void getCompanyData(ArrayList<Object> categoriesArray) {
for (int i = 0; i < categoriesArray.size(); i++) {
Map<String, Object> categoriesInMap = new HashMap<String, Object>();
//ArrayList<Object> categoriesInMapArray = new ArrayList<Object>();
companyMap.put(categoriesArray.get(i), categoriesInMap);
}
this.downloadCompanyData();
}
private void downloadCompanyData() {
companyUrl = companyUrl + delegate.ID;
try {
new DownloadCompanyData().execute(companyUrl).get(10000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class DownloadCompanyData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#SuppressWarnings("unchecked")
#Override
protected void onPostExecute(String result) {
JSONArray companyDataArray;
try {
companyDataArray = new JSONArray(result);
for(int i=0;i<companyDataArray.length();i++){
JSONObject id = companyDataArray.getJSONObject(i);
String catName = id.getString(Controller.CAT_NAME);
if (companyMap.get(catName) != null) {
Markers marker = new Markers(new LatLng(id.getDouble("latitude"), id.getDouble("longitude")), id.getString(Controller.CAT_NAME), id.getString(Controller.ID), id.getString(Controller.SUBSCRIPTION), pinMap.get(catName), id.getString(Controller.TITLE), id.getString(Controller.COMPANY_NAME), id.getString(Controller.WWW), id.getString(Controller.STREET), id.getString(Controller.HOUSE_NUMBER), id.getString(Controller.HOUSE_ADD));
((Map<String,Object>) companyMap.get(catName)).put(id.getString(Controller.TITLE), marker.markerInformationMap);
}
}
delegate.setCompanyHashMap(companyMap);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I guess you're missing the point of the AsyncTask
it's supposed to do all the work in doInBackground() and then use the onPostExecute to deliver it to the UI.
But what you're doing is doing the network operation on doInBackground and doing data parsing on onPostExecute.
Furthermore, a JSON object is a raw data that needs further parsing. You should do all the parsing on the background. For example, let's say your companyData is address, phone number, size and name. You could have a class like this (p.s. I'm writing all this without testing, there will be a little mistake here in there, but you'll get the idea):
public class CompanyData{
private String name, address, phone;
private int size;
public CompanyData(JsonObject jo){
name = jo.getString("name");
address = jo.getString("address");
phone = jo.getString("phone");
size = jo.getInt("size");
}
// put a bunch of get methods here...
// getName(), getAddress(), etc.
}
then on your 'protected Map doInBackground(String... urls) ' you complete the network operation, create the JsonArray, create a Map<String,CompanyData>, loop through the array creating CompanyData objects and placing them into the Map and return the map to your protected void onPostExecute(Map<String,CompanyData> result) and inside the post execute it's just pass this result to the UI.
happy coding.
I always doing something like this..
...
private ProgressDialog pDialog;
ArrayList<HashMap<String, String>> CompanyList;
JSONParser jParser = new JSONParser();
JSONArray Company = null;
static String url_all_company = "http://your_site/files.php";
....
private class CompanyData extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Load data..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
CompanyList = new ArrayList<HashMap<String, String>>();
// Building Parameters if any.. to fetching all data, don't declare any param
List<NameValuePair> param = new ArrayList<NameValuePair>();
param.add(new BasicNameValuePair("uid", uid));
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_company, "POST", param);
// Check your log cat for JSON reponse
Log.d("All Company: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// Company found
// Getting Array of Company
Company = json.getJSONArray(TAG_COMPANIES);
// looping through All Company
for (int i = 0; i < Company.length(); i++) {
JSONObject json = Company.getJSONObject(i);
// Storing each json item in variable
String id = json.getString(TAG_GID);
String name = json.getString(TAG_NAME);
String jml = json.getString(TAG_EMPLOYEE);
String deskripsi = json.getString(TAG_DESKRIPSI);
String logo = json.getString(TAG_LOGO);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_GID, id);
map.put(TAG_NAME, name);
map.put(TAG_EMPLOYEE, jml);
map.put(TAG_DESKRIPSI, deskripsi);
map.put(TAG_LOGO, logo);
// adding HashList to ArrayList
CompanyList.add(map);
}
} else {
// no CompanyList found
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing data ArrayList
adapter=new LazyAdapter(MainActivity.this, CompanyList);
list.setAdapter(adapter);
pDialog.dismiss();
}
}
Related
I've got this code with fetches the "rate" data from an API, along with "rate", I need to get the "name". If I get "name" it often binds it below the "rate".
I need it to join on the same row of the List View, so it is like [Rate Name].
I need to get two objects of a JSON Array and bind it to the array adapter so I can display two objects in the same row of a List View so it is more user friendly.
The code below is of the AsyncTask, the code works fine but I need to add one more object and make sure it is displayed as one rate - one name and then iterating through the loop and adding more as needed in the same order.
public class AsyncTaskParseJson extends AsyncTask<String, String, String> {
// the url of the web service to call
String yourServiceUrl = "eg: URL";
#Override
protected void onPreExecute() {
}
String filename = "bitData";
#Override
protected String doInBackground(String... arg0) {
try {
// create new instance of the httpConnect class
httpConnect jParser = new httpConnect();
// get json string from service url
String json = jParser.getJSONFromUrl(yourServiceUrl);
// parse returned json string into json array
JSONArray jsonArray = new JSONArray(json);
// loop through json array and add each currency to item in arrayList
//Custom Loop Initialise
for (int i = 1; i < 8; i++) {
JSONObject json_message = jsonArray.getJSONObject(i);
// The second JSONObject which needs to be added
JSONObject json_name = jsonArray.getJSONObject(i);
if (json_message != null) {
//add each currency to ArrayList as an item
items.add(json_message.getString("rate"));
String bitData = json_message.getString("rate");
String writeData = bitData + ',' +'\n';
FileOutputStream outputStream;
File file = getFileStreamPath(filename);
// first check if file exists, if not create it
if (file == null || !file.exists()) {
try {
outputStream = openFileOutput(filename, MODE_PRIVATE);
outputStream.write(writeData.getBytes());
outputStream.write("\r\n".getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// if file already exists then append bit data to it
else if (file.exists()) {
try {
outputStream = openFileOutput(filename, Context.MODE_APPEND);
outputStream.write(writeData.getBytes());
outputStream.write("\r\n".getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// below method will run when service HTTP request is complete, will then bind text in arrayList to ListView
#Override
protected void onPostExecute(String strFromDoInBg) {
ListView list = (ListView) findViewById(R.id.rateView);
ArrayAdapter<String> rateArrayAdapter = new ArrayAdapter<String>(BitRates.this, android.R.layout.simple_expandable_list_item_1, items);
list.setAdapter(rateArrayAdapter);
}
}
Just Create Custom Class Messsage:
public class Item{
private String name;
private String rate;
public void Message(String n, String r){
this.name=n;
this.rate=r;
}
// create here getter and setter
}
Now in your background, you have to add name and rate in Message class
Public class MainAcitity extends Activity{
public static List<Item> items= new ArrayList<>();// define in inside the class
// this has to be down on background
Item i=new Item(json_message.getString("name"),json_message.getString("rate"));
items.add(i);
Now pass this listmessge onPostExecute :
ListView list = (ListView) findViewById(R.id.rateView);
ArrayAdapter<String> rateArrayAdapter = new ArrayAdapter<String>(BitRates.this, android.R.layout.simple_expandable_list_item_1, items);
list.setAdapter(rateArrayAdapter);
Is that any helpful for you.
Follow this link.You will get my point.
https://devtut.wordpress.com/2011/06/09/custom-arrayadapter-for-a-listview-android/
I have a AsyncTask for downloading a route from API Google Directions. The task starts at first Activity, where I show the time and the distance of the user to a point, but my map is in the second activity where I need draw the line of the route. My question is how to maintain a unique download task between two tasks (If the download has not completed in first activity), and access the data of the task on two activities.
public class DownloadDirections {
String urlDownload;
PolylineOptions lineOptions = null;
Context context;
String mTime;
String mDistance;
public DownloadDirections (Context context, String urlDownload){
this.urlDownload = urlDownload;
this.context = context;
new DownloadDirectionsTask().execute(urlDownload);
}
// Fetches data from url passed
private class DownloadDirectionsTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
MarkerOptions markerOptions = new MarkerOptions();
String distance = "";
String duration = "";
if(result != null) {
if (result.size() < 1) {
Toast.makeText(context, "No Points", Toast.LENGTH_SHORT).show();
return;
}
}
if(result != null) {
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
if (j == 0) { // Get distance from the list
distance = (String) point.get("distance");
continue;
} else if (j == 1) { // Get duration from the list
duration = (String) point.get("duration");
continue;
}
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
mTime = duration;
mDistance = distance;
}
}
}
}
}
There are lots of options.
Download the entire item in the first activity, pass it to the second as intent data and access in the second activity. You may store the data in the internal storage (Preference, DB or Files depending on the size) if you want, and access accordingly.
You want to execute the task multiple times (one after another):
Keep a reference to the task object, and from the second activity call, make a wait call to the first one.
Want to use a service? No prob. Call the service, download the data, store them if very large. If the data is small, pass them via broadcast. Access them in the activity.
Is that what you wanted?
I want to make my code wait until there is a change anywhere in my class to the variable finaloutcomes. Is there any way to do this? I am carrying this out within an Asynctask, which I posted below.
public HashMap<String,String> checkbetoutcome() {
new LoadAllGamet().execute();
// INSERT CODE HERE
return finaloutcomes;
}
ASYNCTASK
class LoadAllGamet extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args) {
// HttpParams httpParameters = new BasicHttpParams();
// HttpConnectionParams.setConnectionTimeout(httpParameters, 250000);
//HttpConnectionParams.setSoTimeout(httpParameters, 250000);
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url_check_bet);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("param", bet));
// Log.d("CURRENTITEM", currentitem);
try {
post.setEntity(new UrlEncodedFormEntity(params));
} catch (IOException ioe) {
ioe.printStackTrace();
}
try {
HttpResponse response = client.execute(post);
Log.d("Http Post Responsecxxx:", response.toString());
HttpEntity httpEntity = response.getEntity();
InputStream is = httpEntity.getContent();
JSONObject jObj = null;
String json = "";
client.getConnectionManager().closeExpiredConnections();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("<", 0)) {
if (!line.startsWith("(", 0)) {
sb.append(line + "\n");
}
}
}
is.close();
json = sb.toString();
json = json.substring(json.indexOf('{'));
// Log.d("sbsssssssssss", json);
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
allgames = jObj.getJSONArray("bets");
// Log.d("WHAT IS MY ARRAY?", allgames.toString());
for (Integer i = 0; i < allgames.length(); i++) {
HashMap<String,String> statuses = new HashMap<>();
JSONObject c = allgames.getJSONObject(i);
JSONArray currentbet = c.getJSONArray("bet");
Log.d("Single array",currentbet.toString());
// Storing each json item in variable
for (Integer a = 0; a < currentbet.length();a++) {
JSONObject d = currentbet.getJSONObject(a);
String Result = d.getString("Result");
String id = d.getString("gid");
Log.d("RESULTS",Result);
statuses.put(id, Result);
}
allbetsmap.add(i, statuses);
Log.d("ddd", statuses.toString());
Log.d("AAA", allbetsmap.get(i).toString());
}
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
}
catch (IOException e) {
e.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String param) {
Log.d("SIZE",Integer.toString(allbetsmap.size()));
//ArrayList<Map<String,String>> allbetsmap = new ArrayList<>();
//ArrayList<Map<String,String>> passtocheck = new ArrayList<>();
if (allbetsmap.size() == passtocheck.size()) {
for (int i = 0; i < allbetsmap.size();i++) {
if (allbetsmap.get(i).size() == passtocheck.get(i).size()) {
String finaloutcome = "won";
for (String a : allbetsmap.get(i).keySet()) {
String f = allbetsmap.get(i).get(a);
if(f.equals("null")) {
finaloutcome = "open";
}
else if (! (f.equals(passtocheck.get(i).get(a)))) {
finaloutcome = "lost";
break;
}
}
finaloutcomes.put(Integer.toString(i),finaloutcome);
}
}
}
Log.d("Vital",finaloutcomes.toString());
}
}
Ok, forget what I wrote before. I didn't realize you were writing code for android. Here is an improved version of LoadAllGamet. There are two important things here. 1. define as much as possible locally i.e. inside a method or - if that's not possible - inside the class. 2. return the result instead of putting it into some variable.
class LoadAllGamet extends AsyncTask<String, Void, HashMap<String,String>> {
protected HashMap<String,String> doInBackground(String ... args) {
HashMap<String,String> finaloutcomes = new HashMap<>(),
HashMap<Integer, HashMap<String,String>> allbetsmap = new HashMap<>();
HttpClient client = new DefaultHttpClient();
...
Log.d("SIZE",Integer.toString(allbetsmap.size()));
if (allbetsmap.size() == passtocheck.size()) {
...
}
Log.d("Vital",finaloutcomes.toString());
return finaloutcomes;
}
}
Whenever you want to do something that might take some time you should not run
that in the UI thread of you App since it can block your UI.
Instead run it asynchronously. One way of doing this is to use AsyncTask.
Let's assume you want to do something and while that something is being processed
you also want to update the UI (e.g. progress bars) from time to time. And once you
are finished you want to do something else with the result.
Here is one way of writing this.
void doSomething() {
new AsyncTask<String, Progress, Result>() {
protected Result doInBackground(String... args) {
//some code
publishProgress(values);
//some more code
return result;
}
protected void onProgressUpdate(Progress ... values) {
updateProgessBars(values);
}
protected void onPostExecute(Result result) {
doSomethingElse(result);
}
}.execute();
}
The String in new AsyncTask<String, Progress, Result> is the type of the
arguments to doInBackground. Often however you don't really need that unless
you want to pass arguments into execute.
Progress is the type of the values you want to send to onProgressUpdate. That
one you only need if you want to update your UI while the background processing
is still going on.
Result is of course your result type. Whatever you want to happen after
the doInBackground is finished you write into onPostExecute.
I am trying to get values from a json data with AsyncTask. I am getting only the last value and I don't understand why...
I tryed to parse with for each, while but I am doing something wrong :
Here is my code :
private class DecodeData extends AsyncTask<String, Void, String> {
protected ArrayList<HashMap<String, String>> decodedArray;
protected HashMap<String, String> decodedMap;
protected Iterator<String> it;
protected JSONArray m_Array;
protected JSONObject object;
protected String response;
protected String keys;
protected String value;
#SuppressWarnings("unchecked")
#Override
protected String doInBackground(String... params) {
response = params[0];
keys = "";
value = "";
object = null;
decodedArray = new ArrayList<HashMap<String, String>>();
try {
JSONArray arrayResp = new JSONArray(response);
for (int i = 0; i < arrayResp.length(); i++) {
decodedMap = new HashMap<String, String>();
it = arrayResp.getJSONObject(i).keys();
while (it.hasNext()) {
keys = (String)it.next();
value = Base64.DecodeStrToStr((String)arrayResp.getJSONObject(i).get(keys));
decodedMap.put("\""+keys+"\"", "\""+value+"\"");
object = new JSONObject(decodedMap.toString());
Log.i("DECODED MAP : ", object.toString());
m_Array = new JSONArray();
m_Array.put(object);
Log.i("M_ARRAY", ""+m_Array);
}
// decodedArray.add(decodedMap);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// array = new JSONArray(decodedArray);
return m_Array.toString();
}
I am using Volley to get response. After that, I create a JSONArray with this response and I get all keys/values from it. I put all of them in my Hashmap. But when i'm putting keys/values here : m_Array.put(object), it puts only the last value of my json data. Anybody has an idea of what I'm making wrong ?
Please create JSONArray before starting for loop..
m_Array = new JSONArray();
JSONArray arrayResp = new JSONArray(response);
for (int i = 0; i < arrayResp.length(); i++) { ....
I have such JSONparser class:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
and such activity:
public class BankExchangersListActivity extends ExpandableListActivity {
private static String url;
// JSON Node names
private static final String TAG_Exchangers = "bank_exchangers";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_address = "address";
private static final String TAG_location_name = "location_name";
private static final String TAG_latitude = "latitude";
private static final String TAG_longitude = "longitude";
private static final String TAG_exchanger_type_name = "exchanger_type_name";
private static final String TAG_exchanger_curr_value = "value";
private static final String TAG_currency_list_name = "currency_list_name";
private static final String TAG_direction_of_exchange_name = "direction_of_exchange_name";
JSONArray banks = null;
JSONArray exc_currencies = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
String bank;
bank = this.getIntent().getStringExtra("Bank_id");
url = "****/**_**_***_list/"+bank+".json";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bank_exchangers_list);
// Hashmap for ListView
ArrayList<HashMap<String, String>> contactList = new ArrayList<HashMap<String, String>>();
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(url);
ArrayList result = new ArrayList();
try {
// Getting Array of Contacts
banks = json.getJSONArray(TAG_Exchangers);
// looping through All Contacts
for(int i = 0; i < banks.length(); i++){
JSONObject c = banks.getJSONObject(i);
exc_currencies = c.getJSONArray("currency_values");
HashMap<String, String> map2 = new HashMap<String, String>();
ArrayList secList = new ArrayList();
for(int k = 0; k < exc_currencies.length(); k++){
JSONObject m = exc_currencies.getJSONObject(k);
String currency = m.getString(TAG_exchanger_curr_value);
String currency_list_name = m.getString(TAG_currency_list_name);
String direction_of_exchange_name = m.getString(TAG_direction_of_exchange_name);
Log.e("wazzzup", currency); //here is trouble: how to do new array with linking to parent?
HashMap child = new HashMap();
child.put(TAG_exchanger_curr_value, currency );
child.put(TAG_currency_list_name, currency_list_name );
child.put(TAG_direction_of_exchange_name, direction_of_exchange_name );
secList.add(child);
}
// Storing each json item in variable
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
Log.e("name", name); //here is trouble: how to do new array with linking to parent?
String address = c.getString(TAG_address);
String location_name = c.getString(TAG_location_name);
String latitude = c.getString(TAG_latitude);
String longitude = c.getString(TAG_longitude);
String exchanger_type_name = c.getString(TAG_exchanger_type_name);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_ID, id);
map.put(TAG_NAME, name);
map.put(TAG_address, address);
map.put(TAG_location_name, location_name);
map.put(TAG_latitude, latitude);
map.put(TAG_longitude, longitude);
map.put(TAG_exchanger_type_name, exchanger_type_name);
// adding HashList to ArrayList
contactList.add(map);
result.add(secList);
}
} catch (JSONException e) {
e.printStackTrace();
}
/*ListAdapter adapter = new SimpleAdapter(this, contactList,
R.layout.bank_exchanger_list_element,
new String[] { TAG_NAME, TAG_location_name, TAG_address, TAG_exchanger_type_name, TAG_latitude, TAG_longitude }, new int[] {
R.id.bank_e_n, R.id.nas_punkt_e_n , R.id.adress_obm_e_n , R.id.tip_obm_e_n , R.id.shirota_e_n , R.id.dolgota_e_n });
setListAdapter(adapter);*/
SimpleExpandableListAdapter expListAdapter =
new SimpleExpandableListAdapter(
this,
contactList,
R.layout.bank_exchanger_list_element,
new String[] { TAG_NAME, TAG_location_name, TAG_address, TAG_exchanger_type_name, TAG_latitude, TAG_longitude },
new int[] {
R.id.bank_e_n, R.id.nas_punkt_e_n , R.id.adress_obm_e_n , R.id.tip_obm_e_n , R.id.shirota_e_n , R.id.dolgota_e_n },
result, //something goes here
R.layout.exchanger_currencies,
new String[] {TAG_exchanger_curr_value, TAG_currency_list_name, TAG_direction_of_exchange_name},
new int[] { R.id.currencyvalue_e_n, R.id.currency_list_name_e_n, R.id.direction_of_exchange_e_n}
);
setListAdapter( expListAdapter );
ExpandableListView elv = (ExpandableListView) getExpandableListView();
for(int i=0; i < expListAdapter.getGroupCount(); i++)
elv.expandGroup(i);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.bank_exchangers_list, menu);
return true;
}
}
On android 2.3.3 it works properly. But on 4.x i see errors, after searching I understood that I need to use AsyncTask. Is it true?
But how do I use it here? If there are any useful examples, please let me know.
Just how to get it working on Android 4.x?
You should already use AsyncTask under Android 2.x. It greatly improves responsiveness. Here is a fragment from my MEGA API library (currently under development):
private class AsyncRequestConnection extends AsyncTask<Void, Void, String> {
private final Request request;
public AsyncRequestConnection(Request request) {
this.request = request;
}
#Override
protected String doInBackground(Void... params) {
try {
HttpPost p = createRequestHttpMessage(request);
String resp = new String(stripResponse(getRequestClient().execute(p)));
Log.v(TAG, resp);
return resp;
} catch (Exception e) {
Log.e(TAG, "Cannot complete API request", e);
cancel(false);
return null;
}
}
#Override
protected void onCancelled() {
request.backoff();
if (request.hasReachedMaxBackoff()) {
request.cancel(R.string.error_internal);
} else {
requestQueue.enqueue(request);
}
requestConnection = null;
nextRequest();
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
request.attachResponse(result);
request.handleResponse();
requestConnection = null;
nextRequest();
} else {
request.cancel(R.string.error_internal);
}
}
}
doInBackgroud() is the only method that is run on a different thread. Here, all your costly operations should happen.
getRequestClient() returns a HttpClient (AndroidHttpClient.newInstance(AGENT_NAME) or reused object for multiple requests in a row).
Since you are running muliple threads here, make sure doInBackground() does not access any global data structure. In my example, get getRequestClient() is sure to be only called from this location and there is only one such AsyncTask at any time. Otherwise you need some kind of mutex. Also, the Request object is sure to used by this class exlusively. Event handling (call-back methods) is implemented in the Request object as well but for simpler tasks you could simply do everything you want to do in onCancel() and onPostExecute().
If you only want to download a JSON object and parse it, you probably won't even need a constructor and private member variables. Simply replace the first Void by String to pass the URL string to doInBackground() and replace String by JSONObject.