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'm using Volley however I'm having some problems with the JSON parsed data most likely because volley doesn't implement something like AsyncTask's onPostExecute() and I'm getting some duplicated data on wrong list items.
Then I came across this: https://github.com/yakivmospan/volley-request-manager#custom-listener-implementation-
Has anyone use it? How can I add it to my current Volley code?
More details about my problem here Volley not sending correct data. How to implement an alternative to onPostExecute()?
UPDATE
As requested, some code. Here's a button that calls a method on another class that uses Volley to request some raw JSON data (NovaJSON) and then send the JSON to a parser class (NovaParser):
info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String instanceDetail = NovaJSON.shared().receiveDetail(getId());
Dialog dialog = new Dialog(v.getContext());
dialog.setContentView(R.layout.instances_info);
TextView image = (TextView) dialog.findViewById(R.id.imageInstance);
TextView flavor = (TextView) dialog.findViewById(R.id.flavorInstance);
dialog.setTitle(name.getText() + " Details");
if (instanceDetail != null) {
image.setText(" \u2022 image : " + NovaParser.shared().parseImages(instanceDetail));
flavor.setText(" \u2022 flavor : " + NovaParser.shared().parseFlavor(instanceDetail));
}
dialog.show();
}
});
This is the method that does the Volley request on the NovaJSON class:
public void getJSONdetail() {
final String authToken = getAuth();
String novaURL = getNova();
novaURL = novaURL+"/servers/"+id;
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Nova on Response", response.toString());
setNovaJSONdetail(response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
setNovaJSONdetail(error.toString());
}
}
) {
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("X-Auth-Token", authToken);
params.put("User-Agent", "stackerz");
params.put("Accept", "application/json");
params.put("Content-Type", "application/json; charset=utf-8");
return params;
}
};
queue = VolleySingleton.getInstance(this).getRequestQueue();
queue.add(getRequest);
}
It then sends the JSON from the server as a string to be parsed using the following methods:
public static String parseImages(String imagesDetail){
ArrayList<HashMap<String, String>> imagesList = NovaParser.shared().getImagesList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(imagesDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject image = server.getJSONObject("image");
if (imagesList !=null){
temp = image.getString("id");
for (Map<String,String> map : imagesList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
public static String parseFlavor(String instanceDetail){
ArrayList<HashMap<String, String>> flavorList = NovaParser.shared().getFlavorList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(instanceDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject flavor = server.getJSONObject("flavor");
if (flavorList !=null){
temp = flavor.getString("id");
for (Map<String,String> map : flavorList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
When I press the button once the dialog is displayed with empty values. When I press it the second time I get the correct parsed data. Basically first time I click the button the instanceDetail string is null because Volley didn't finish doing its thing then I click the 2nd time it loads the values accordingly because it finally finished the 1st request.
I understand Volley is asynchronous, the requests happen in parallel and the responses sometimes are not immediate however I need some sort of progress bar or spinning wheel to give the user some feedback that the app is waiting for data. It could be done with AsyncTask however it doesn't seem to be possible with Volley.
I think your problem is not because of Volley.
Check the parameters you send and receive.
However if you need onPostExcecute you have Volley's callback:
Response.Listener<JSONObject> and Response.ErrorListener() which are called after the request.
About Volley request manager just switch all your volley calls with appropriate Volley request manager calls
I solved my problem by dumping Volley altogether and moving to Retrofit. I setup all the calls to be sync/blocking, worked out the exceptions/errors using try/catches and setup a short timeout on the OkHTTP client. Now it's working as I wanted.
okay guys, here is the thing, I have one application consuming ODATA service, in SMP server, I'm getting this Data like this:
public class callService extends AsyncTask<Void, Void, ArrayList<String>>
{
public ArrayList<String> doInBackground(Void... params)
{
ODataConsumer c = ODataJerseyConsumer.create("http://MyUrlService:8080");
List<OEntity> listEntities = c.getEntities("MYENTITYTOCONSUME").execute().toList();
System.out.println("Size" + listEntities.size());
if (listEntities.size() > 0)
{
for (OEntity entity : listEntities)
{
zmob_kunnr.add((String) entity.getProperty("Name1").getValue()
+ " - "
+ entity.getProperty("Kunnr").getValue().toString());
}
}
return zmob_kunnr;
}
protected void onPostExecute(ArrayList<String> result)
{
super.onPostExecute(result);
adapter = new ArrayAdapter<String>(ConsumoKnuur.this, android.R.layout.simple_list_item_1, result);
list.setAdapter(adapter);
}
}
Okay I got this solution from web and could implement as list, and I need to store this entity which one is a List of customers and get the two attributes from this entity and save in my database so:
Entity Customer:Custormer_ID, Customer_Name
Here is my code to call my sqlite:
public void sqlite()
{
sql_obj.open();
sql_obj.deleteAll();
for(int i=0; i < zmob_kunnr.size(); i++)
{
sql_obj.insert(zmob_kunnr.get(i).toString(), zmob_kunnr.get(i).toString() );
}
sql_obj.close();
}
And my SQLite:
private static final String TABLE_CLIENTE = "CREATE TABLE "
+ TB_CLIENTE
+ "(ID_CLIENTE INTEGER PRIMARY KEY AUTOINCREMENT, " //Id for controller my logics
+ " Kunnr TEXT , " //customer ID
+ " Name1 TEXT );"; //customer_name
public long insert(String name1, String Kunnr)
{
ContentValues initialValues = new ContentValues();
initialValues.put("Name1", Name1); //Customer_Name
initialValues.put("Kunnr", Kunnr); //Customer_ID
return database.insert(TB_CLIENTE, null, initialValues);
}
And off course my other methods, that is not important, so whats happening when I run my "for" in the sql call method, I get the size() of the list and the rows of the list and store the entire row in the one column of the database each time, so I got two different tables with the same values,
how can I change solve this problem instead of consume in list I need to consume in array ? or I need to create a method that get the list values and after a ,(coma) , create two differents objects to store these data ??
I took a long look in the internet and didn't find nothing, probably it's because i don't know yet, how so, I don't know for what I'm looking for it, I'm using the odata4j API and here is the link of the documentation, http://odata4j.org/v/0.7/javadoc/
I'm new on programming, so I'm really in trouble with this, any suggestions any helps will be truly, appreciate,
Thanks a lot and have a nice day !!!
You can add each entity to the `ArrayList' array by doing the following:
for (OEntity entity : listEntities) {
zmob_kunnr.add(entity);
}
This will allow you to access the data contained in the entity via getProperty() when inserted into the database.
The following statement is also not needed, as the for each loop runs through every element in the list, thus for (OEntity entity : listEntities) will not execute if the list is empty.
if (listEntities.size() > 0) {
...
}
If you have multiple ODataConsumers, you have two choices, depending on your requirements (if I understand you question correctly):
You can sequentially get each ODataConsumer, get the listEntities, and add it to the zmob_kunnr list, and after the list items are added to the database, clear the zmob_kunnr list, and call doInBackground with a new URL. This is what your current solution allows.
It appears to need to know which property is associated with a URL when reading the values into the DB. You can use a POJO as a holder for the entity and its list of properties. You can now add and remove properties. Note that properties will be removed in the same order they where inserted.
public class OEntityHolder {
private final OEntity entity;
private Queue<String> properties;
public OEntityHolder(OEntity entity) {
this.entity = entity;
this.properties = new LinkedBlockingQueue<>();
}
public OEntity getEntity() {
return this.entity;
}
public void addProperty(String property) {
this.properties.add(property);
}
public void removeProperty() {
this.properties.poll();
}
}
This will require a change to the list holding the entities:
ArrayList<OEntityHolder> zmob_entity_holders = new ArrayList<>();
If you would like to add all the entities from the different URLs at the same time, you will need to have access to all the URLs when doInBackground is called. Something like this:
public ArrayList<OEntityHolder> doInBackground(Void... params) {
String [][] urls = {{"http:MyUrl/ZMOB_FECODSet", "Name1", "Fecod"},
{"http:MyUrl/ZMOB_OTEILSet", "Name2", "Oteil"},
{"http:MyUrl/ZMOB_KUNNRSet", "Name3", "Kunnr"},
{"http:MyUrl/ZMOB_BAULTSet", "Name4", "Bault"}};
for (String [] urlProp:urls) {
//Here you get the list of entities from the url
List<OEntity> listEntities = ODataJerseyConsumer.create(urlProp[0]).getEntities("MYENTITYTOCONSUME").execute().toList();
for (OEntity entity:listEntities) {
OEntityHolder holder = new OEntityHolder(entity);
for (int i = 1; i < urlProp.length; i++)
holder.addProperty(urlProp[i]);
zmob_entity_holders.add(holder);
}
}
//At this point, all of the entities associated with the list of URLS will be added to the list
return zmob_entity_holders;
}
You now have ALL of the entities associated with the list of URLs in zmob_kunnr. Before you can and can insert then into the DB like so:
for (OEntityHolder holder : zmob_entity_holders) {
sql_obj.insert(holder.getEntity().getProperty(holder.removeProperty()).toString(), holder.getEntity().getProperty(holder.removeProperty()).toString());
}
If each entity has a associated name, you can store the names in a map, where the key is the URL and the value the name.
HashMap<String, String> urlEntityNames = new HashMap<>();
urlEntityNames.put("http://MyUrlService:8080", "MYENTITYTOCONSUME");
...//Add more URLs and entity names
You can then, when running through the list of entities, do a look-up in the map to find the correct name:
List<OEntity> listEntities = ODataJerseyConsumer.create(url).getEntities(urlEntityNames.get(url)).execute().toList();
I hope this helps, if I misunderstood you just correct me in the comments.
EDIT: Added list of URLs, holder and DB insert.
I guess i found a solution, but my log cat, is giving an exception to me any updtades about my 2nd doInBackgroundBault (Material),
public class callServiceCliente extends AsyncTask<Void, Void, ArrayList<OEntity>> {
protected void onPreExecute() {
progressC = ProgressDialog.show(Atualizar_Dados.this, "Aguarde...", "Atualizando Clientes", true, true);
}
public ArrayList<OEntity> doInBackground(Void... params) {
ODataConsumer ccli = ODataJerseyConsumer.create(URL);
List<OEntity> listEntitiesKunnr = ccli.getEntities("ZMOB_KUNNRSet").execute().toList();
System.out.println("Size" + listEntitiesKunnr.size());
for (OEntity entityKunnr : listEntitiesKunnr) {
zmob_kunnr.add(entityKunnr);
}
return zmob_kunnr;
}
protected void onPostExecute(ArrayList<OEntity> kunnr) {
super.onPostExecute(kunnr);
try {
sql_obj.open();
sql_obj.deleteAll();
for (int k = 0; k < zmob_kunnr.size(); k++) {
sql_obj.insertCliente(zmob_kunnr.get(k).getProperty("Kunnr").getValue().toString().toUpperCase(), zmob_kunnr.get(k).getProperty("Name1").getValue().toString().toUpperCase());
}
sql_obj.close();
} catch (Exception e) {
}
try {
clienteAdapter = new ArrayAdapter<OEntity>(Atualizar_Dados.this, android.R.layout.simple_list_item_1, kunnr);
listCliente.setAdapter(clienteAdapter);
} catch (Exception eq) {
}
progressC.dismiss();
new callServiceMaterial().execute();
}
}
public class callServiceMaterial extends AsyncTask<Void, Void, ArrayList<OEntity>> {
protected void onPreExecute() {
progressM = ProgressDialog.show(Atualizar_Dados.this, "Aguarde...", "Atualizando Materiais", true, true);
}
public ArrayList<OEntity> doInBackground(Void... params) {
ODataConsumer cmat = ODataJerseyConsumer.create(URL);
List<OEntity> listEntitiesBault = cmat.getEntities("ZMOB_BAULTSet").filter("IErsda eq '20141101'").execute().toList();
System.out.println("Size" + listEntitiesBault.size());
for (OEntity entityBault : listEntitiesBault) {
zmob_bault.add(entityBault);
}
return zmob_bault;
}
protected void onPostExecute(ArrayList<OEntity> bault) {
super.onPostExecute(bault);
try {
sql_obj.open();
sql_obj.deleteAll();
for (int b = 0; b < zmob_bault.size(); b++) {
sql_obj.insertMaterial(zmob_bault.get(b).getProperty("Matnr").getValue().toString().toUpperCase(), zmob_bault.get(b).getProperty("Maktxt").getValue().toString().toUpperCase());
}
sql_obj.close();
} catch (Exception e) {
}
try {
materialAdapter = new ArrayAdapter<OEntity>(Atualizar_Dados.this, android.R.layout.simple_list_item_1, bault);
listMaterial.setAdapter(clienteAdapter);
} catch (Exception eq) {
}
progressM.dismiss();
new callServiceProblema().execute();
}
}
public class callServiceProblema extends AsyncTask<Void, Void, ArrayList<OEntity>> {
protected void onPreExecute() {
progressProb = ProgressDialog.show(Atualizar_Dados.this, "Aguarde...", "Atualizando Problemas", true, true);
}
public ArrayList<OEntity> doInBackground(Void... params) {
ODataConsumer cprob = ODataJerseyConsumer.create(URL);
List<OEntity> listEntitiesFecod = cprob.getEntities("ZMOB_FECODSet").execute().toList();
System.out.println("Size" + listEntitiesFecod.size());
for (OEntity entityFecod : listEntitiesFecod) {
zmob_fecod.add(entityFecod);
}
return zmob_fecod;
}
protected void onPostExecute(ArrayList<OEntity> fecod) {
super.onPostExecute(fecod);
try {
sql_obj.open();
sql_obj.deleteAll();
for (int f = 0; f < zmob_fecod.size(); f++) {
sql_obj.insertProblema(zmob_fecod.get(f).getProperty("Fecod").getValue().toString().toUpperCase(), zmob_fecod.get(f).getProperty("Kurztext").getValue().toString().toUpperCase());
}
sql_obj.close();
} catch (Exception e) {
}
try {
problemaAdapter = new ArrayAdapter<OEntity>(Atualizar_Dados.this, android.R.layout.simple_list_item_1, fecod);
listProblema.setAdapter(problemaAdapter);
} catch (Exception eq) {
}
progressProb.dismiss();
new callServiceProcedencia().execute();
}
}
public class callServiceProcedencia extends AsyncTask<Void, Void, ArrayList<OEntity>> {
protected void onPreExecute() {
progressProc = ProgressDialog.show(Atualizar_Dados.this, "Aguarde...", "Atualizando base de dados", true, true);
}
public ArrayList<OEntity> doInBackground(Void... params) {
ODataConsumer c = ODataJerseyConsumer.create(URL);
List<OEntity> listEntitiesProcedencia = c.getEntities("ZMOB_OTEILSet").execute().toList();
System.out.println("Size" + listEntitiesProcedencia.size());
for (OEntity entityProcedencia : listEntitiesProcedencia) {
zmob_oteil.add(entityProcedencia);
}
return zmob_oteil;
}
protected void onPostExecute(ArrayList<OEntity> oteil) {
super.onPostExecute(oteil);
try {
sql_obj.open();
sql_obj.deleteAll();
for (int o = 0; o < zmob_oteil.size(); o++) {
sql_obj.insertCliente(zmob_oteil.get(o).getProperty("Fecod").getValue().toString().toUpperCase(), zmob_oteil.get(o).getProperty("Kurztext").getValue().toString().toUpperCase());
}
sql_obj.close();
} catch (Exception e) {
}
try {
procedenciaAdapter = new ArrayAdapter<OEntity>(Atualizar_Dados.this, android.R.layout.simple_list_item_1, oteil);
// listCliente.setAdapter(clienteAdapter);
} catch (Exception eq) {
}
progressProc.show(Atualizar_Dados.this, "Finalizado", "Base de dados atualizada", true, true).dismiss();
Toast.makeText(Atualizar_Dados.this, "Base de dados atualizada com sucesso", Toast.LENGTH_LONG).show();
}
}
Okay, so here is the solution that i find, and i couldn't insert your solution because, when i put inser.add(entity), they didn't show me the properties but if you have a better way to do what i did, i will really appreciate,
and by the way i need to query this consume by range date in the filter(). like i did here...
List listEntitiesBault = cmat.getEntities("ZMOB_BAULTSet").filter("IErsda eq '20141101'").execute().toList(); but isn't working, so i don't have any ideas why, i saw couple close solution on the internet and saw fields like .top(1) and .first(); that i didn't understand...
thanks a lot !!!
I am trying to get values from my User class (holding all the user information for the logged in user.
It is set once logged in, and it is printing out in the log just fine, but then when calling from the class that instantiates it, it returns a null? Here is the code:
public ApiConnector api;
public String ID;
public String USERNAME = null;
public String NAME = null;
public String LASTNAME = null;
public String PASSWORD = null;
public String EMAIL = null;
public User(String id) {
this.ID = id;
this.api = new ApiConnector();
new GetUserDataClass().execute(api);
}
private class GetUserDataClass extends AsyncTask<ApiConnector,Boolean,JSONArray> {
#Override
protected JSONArray doInBackground(ApiConnector... params) {
return params[0].getAllUserData(ID);
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
if(jsonArray != null) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = null;
try {
json = new JSONObject();
json = jsonArray.getJSONObject(i);
if(!json.getString("username").isEmpty()) {
setUsername(json.getString("username"));
Log.d("username", getUsername());
}
if(!json.getString("firstname").isEmpty()) {
setName(json.getString("firstname"));
Log.d("name", getName());
}
if(!json.getString("lastname").isEmpty()) {
setLastName(json.getString("lastname"));
Log.d("lastname", getLastName());
}
if(!json.getString("email").isEmpty()) {
setEmail(json.getString("email"));
Log.d("email", getEmail());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} else {
Log.d("hey", "hey");
}
}
The logcat output is:
05-19 02:03:55.996: W/EGL_emulation(4367): eglSurfaceAttrib not implemented
05-19 02:03:55.996: D/username(4367): Me
05-19 02:03:55.996: D/name(4367): Me
05-19 02:03:55.996: D/lastname(4367): Mememe
05-19 02:03:55.996: D/email(4367): me#example.com
I have all appropriate getters and setters in the class (as you can see in the above code, working fine.
Here is the Menu class (that is returning the null):
public class Menu extends Activity {
private String ID;
private User user;
public TextView tvusername;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
init();
}
public void init() {
Bundle bundle = getIntent().getExtras();
ID = bundle.getString("id");
user = new User(ID);
tvusername = (TextView) findViewById(R.id.tvUsername);
tvusername.setText(ID + " " + user.getEmail());
}
}
Here is what it looks like on the emulator:
I have spent the last day and a half looking for solutions, but came up empty. Please would you help?
you can use
new GetUserDataClass().execute(api).get();
so that system will wait to complete AsyncTask. and you will get the id.
You are loading user data in an AsyncTask... and that's good because it seems to perform some network operation.
It means that user data loading is performed asynchronously... and so not available immediately.
You have a callback onPostExecute in the AsyncTask : use it to update the UI with something like this code :
//you need to initialize it in the AsyncTask constrtuctor
final Activity myActivity;
#Override
protected void onPostExecute(JSONArray jsonArray) {
//json parsing code
//...
//and finally update the UI
new Handler(Looper.getMainLooper()).post(
new Runnable(){
public void run(){
TextView tvusername = (TextView) myActivity.findViewById(R.id.tvUsername);
tvusername.setText(ID + " " + getEmail());
}
}
);
}
I think you forgot to use static word in User class object creation while setting data.
other wise it will create new instance every time and that object will not show your data.
I solved it by using the Singleton Design Pattern in my User class. Just so people can look that up to solve this if they are having the same issues!
Cheers and thanks for all the replies!
This is regarding Weatherforecastapp using Volley..
How do we replace the following code with Volley?
Since we are new to android we are finding it difficult to implement Volley.
private class JSONWeatherTask extends AsyncTask<String, Void, Weather> {
#Override
protected Weather doInBackground(String... params) {
Weather weather = new Weather();
String data = ( (new WeatherHttpClient()).getWeatherData(params[0], params[1]));
try {
weather = JSONWeatherParser.getWeather(data);
System.out.println("Weather ["+weather+"]");
// Let's retrieve the icon
weather.iconData = ( (new WeatherHttpClient()).getImage(weather.currentCondition.getIcon()));
} catch (JSONException e) {
e.printStackTrace();
}
return weather;
}
#Override
protected void onPostExecute(Weather weather) {
super.onPostExecute(weather);
if (weather.iconData != null && weather.iconData.length > 0) {
Bitmap img = BitmapFactory.decodeByteArray(weather.iconData, 0, weather.iconData.length);
imgView.setImageBitmap(img);
}
cityText.setText(weather.location.getCity() + "," + weather.location.getCountry());
temp.setText("" + Math.round((weather.temperature.getTemp() - 275.15)));
condDescr.setText(weather.currentCondition.getCondition() + "(" + weather.currentCondition.getDescr() + ")");
}
}
The good news is that Volley is much easier to use than AsyncTask! :)
Volley has a a few types of requests that it can make. For your implementation, it looks like you are retrieving JSON. Volley has special request for JSONObject and JSONArray, so you would use whichever makes sense for you.
Here is a basic outline of how you would replace your code with Volley. Note that the onResponse is the callback (like onPostExecute in AsyncTask).
private class WeatherTask{
public void getWeatherData() {
// Create a single queue
RequestQueue queue = Volley.newRequestQueue(this);
// Define your request
JsonObjectRequest getRequest = new JsonObjectRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JsonObject jsonObject) {
// Parse JSON here
}
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
// Show Error message
Log.e("Error Response: ", volleyError.toString());
}
}
);
// add it to the Request Queue
queue.add(getRequest);
}
}
Here is a great talk on Volley, to learn more about it: https://developers.google.com/events/io/sessions/325304728