Is there any way to break AsyncTaskResult>>
into to list ?
or get like 30,40,.. value of it only?
i have a Async class and it return the result of webservice fetch to adapter.
now because of huge data i want to split the result into seperate segment with passing
number of result to async class.
here is myasync class :
protected AsyncTaskResult<ArrayList<HashMap<String, String>>> doInBackground(
String... arg0) {
String xml = "Get String from my web service class"
myXmlParsingClass myparser = new myXmlParsingClass (xml, "getitem");
myparser .runParser();
AsyncTaskResult<ArrayList<HashMap<String, String>>> myresult = new AsyncTaskResult<ArrayList<HashMap<String, String>>>(myXmlParsingClass .getParsedData());
return myresult ;
}
and my asynctaskresult :
public class AsyncTaskResult<T> {
private T result = null;
private Exception error = null;
public T getResult() {
return result;
}
public Exception getError() {
return error;
}
public AsyncTaskResult(T result) {
super();
this.result = result;
}
public AsyncTaskResult() {
super();
}
public AsyncTaskResult(Exception error) {
super();
this.error = error;
}
this is what i have done so far :
in the getview method inside my adapter i made second method to pass a number to async class:
MyAsyncClass ma = new MyAsyncClass(myview,userid,5);
in MyAsyncClass :
public MyAsyncClass ( View context,String _id) {
this.targetCtx = context ;
id = _id;
}
public MyAsyncClass ( View context,String _id,int _ID_To_Show) {
this.targetCtx = context ;
id = _id;
ID_To_Show= _ID_To_Show;
}
and on PostExecute method :
if(ID_To_Show >0 ){
MySecondAdapter Madapter = new MySecondAdapter(targetCtx, myresult.getResult(),ID_To_Show);
mylist.setAdapter(Madapter);
}else{
MySecondAdapter Madapter = new MySecondAdapter(targetCtx, myresult.getResult());
mylist.setAdapter(Madapter);
and finally in MySecondAdapter i added this :
public MySecondAdapter(View a, ArrayList<HashMap<String, String>> id,int _ID_To_Show) {
idfromhayoolafetch = id;
myinflater = (LayoutInflater) AppContext.getAppContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ID_To_Show= _ID_To_Show;
}
public MySecondAdapter(View a, ArrayList<HashMap<String, String>> id) {
idfromhayoolafetch = id;
myinflater = (LayoutInflater) AppContext.getAppContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
if(ID_To_Show>0){
return ID_To_Show;
}else{
return idfromhayoolafetch.size();
}
}
this approch show the amount of item i want to show in each call and i can pass value to it
but is other way i can do this ?
problem is i cant ask hayoola to limit the value in respond.
Such a request should be handled by server it self.
As in server should accept number of items to return and only send that many items.
But still if you want async task to handle it you can do following:
protected AsyncTaskResult<ArrayList<HashMap<String, String>>> doInBackground(
String... arg0) {
String xml = "Get String from my web service class"
myXmlParsingClass myparser = new myXmlParsingClass (xml, "getitem");
myparser .runParser();
AsyncTaskResult<ArrayList<HashMap<String, String>>> myresult = new AsyncTaskResult<ArrayList<HashMap<String, String>>>(myXmlParsingClass .getParsedData());
ArrayList<HashMap<String, String>> result=myresult.getResult();
myresult.setResult(result.subList(0,maxItems));//maxItems=30 set it while creating async task object
return myresult ;
}
Related
I have this methods
private void changeContacts() {
if (mOnlyDisplayContacts) {
listContact = fetchContactResponse(mView);
} else {
// Other code
}
contactAdapter = new ContactsAdapter(context, listContact, this);
mContactsList.setAdapter(mContactAdapter);
mContactAdapter.notifyDataSetChanged();
}
private List<Contact> fetchContactResponse(final String view) {
AsyncContactSearch mLoadContactTask = new AsyncContactSearch(context, limit, offset, view, search);
try {
listContacts = mLoadContactTask.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return listContacts;
}
Class Task
public class AsyncContactSearch extends AsyncTask<Void, Void, List<LinphoneContact>> {
private Context context;
private int limit, offset;
private String view, search;
public AsyncContactSearch(Context context, int limit, int offset, String view, String search) {
this.context = context;
this.limit = limit;
this.offset = offset;
this.view = view;
this.search = search;
}
#Override
protected List<Contact> doInBackground(Void... voids) {
String domain = SharedPreferencesManager.getDomain(context);
String authToken = SharedPreferencesManager.getAuthtoken(context);
final List<Contact> listContact = new ArrayList<>();
RestAPI RestAPI = RetrofitHelper.create(RestAPI.class, domain);
Call<ContactList> searchWithTerms =
userRestAPI.searchWithTerms(authToken, "", limit, offset);
searchWithTerms.enqueue(
new Callback<ContactList>() {
#Override
public void onResponse(Call<ContactList> call, Response<ContactList> response) {
ContactList contactList = response.body();
if (contactList == null) {
return;
}
List<Contact> contacts = contactList.getRows();
for (Contact c : contacts) {
listContact.add(
ContactsManager.getInstance().addFromAPI(c));
}
}
#Override
public void onFailure(Call<ContactList> call, Throwable throwable) {}
});
Collections.sort(
listContact,
new Comparator() {
public int compare(Object o1, Object o2) {
String x1 = ((LinphoneContact) o1).getCompany();
String x2 = ((LinphoneContact) o2).getCompany();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
}
String x3 = ((LinphoneContact) o1).getFirstName();
String x4 = ((LinphoneContact) o2).getFirstName();
return x3.compareTo(x4);
}
});
return listContact;
}
}
The problem is (debugging the code) that while the search task is still running, the method is triggered immediately contactAdapter = new ContactsAdapter(context, listContact, this);listContact is empty,then the execution goes on assigns the Adapter to the ListView, while the recovery task goes on and inserts the elements into the List, on the screen the ListView remains empty
You are using the retrofit for API call so no need to use AsyncTask. The retrofit will make the API call asynchronously and deliver the result in callback onResponse(). Just move your logic inside callback onResponse().
I know this question has been asked a lot but I still can't figure out how on my code. I'm trying to get values out of this block of code:
private void getAnswerKey(){
class GetAnswerKey extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
JSON_STRING = s;
showAnswerKey();
}
#Override
protected String doInBackground(Void... params) {
RequestHandler rh = new RequestHandler();
String s = rh.sendGetRequest(Configuration.URL_GET_ANSWER);
return s;
}
}
GetAnswerKey gA = new GetAnswerKey();
gA.execute();
}
private void showAnswerKey () {
correctAnswers = new ArrayList<Integer>();
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray result = jsonObject.getJSONArray(Configuration.TAG_JSON_ARRAY);
for (int i = 0; i < result.length(); i++) {
JSONObject jo = result.getJSONObject(i);
int answerKey = jo.getInt(Configuration.TAG_ANSWERKEY);
correctAnswers.add(answerKey);
System.out.println((i + 1) + "a. " + options[correctAnswers.get(i)]); //data are there
}
} catch (JSONException e) {
e.printStackTrace();
}
}
How do I access correctAnswers arrayList on my main activity? correctAnswers itself isn't empty in this code, but when I tried accessing it on other method, it's null. I've tried passing data to other method. Still return null. I have the arrayList as global variable. Any ideas how??
Like suvojit_007 might have correctly assumed, you may be attempting to access the arraylist before it is populated..
You can use interfaces. Create your interface...
public interface ResponseInterface {
public void getResponse(String data);
}
In your AsyncTask declare your interface
private ResponseInterface responseInterface;
Create a constructor within the AsyncTask with the interface as a parameter
public GetAnswerKey(ResponseInterface responseInterface) {
this.responseInterface = responseInterface;
}
Within your onPostExecute, call the interface
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
responseInterface.getResponse(s);
}
... and finally when executing your AsyncTask, do this...
new GetAnswerKey(new ResponseInterface() {
#Override
public void getResponse(String data) {
// do whatever you want with your answers here.
// Also, whatever function that is accessing the
// arrayList, call it here, that way you avoid any
// possibility of the arrayList being null
}
}).execute();
I want to get string from arraylist inside oncreateview fragment but i cant figure itout since no position index has been pass. get(position) return error.
String price = arrayList.get(position).getPrice();
i need to get string price and settext for price.this is my main concern.
this values should return from arraylist.
this is response JSON array from volley using mysingleton.
Single Product Response: [{"price":"75","date":"2017-07-13 03:25:31","pk_i_id":"4"}]
this main activty fragment
public class MainActivityFragment extends Fragment {
private TextView product,price,date,title;
private String product_id;
ArrayList<ProductItem> arrayList = new ArrayList<>();
Context context;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_activity, container, false);
product = (TextView) view.findViewById(R.id.tv1);
title = (TextView) view.findViewById(R.id.tvTitle);
price = (TextView) view.findViewById(R.id.tvPrice);
date = (TextView) view.findViewById(R.id.tvDate);
if (getArguments() != null) {
Log.i(TAG, "getArgument is not null");
product_id = getArguments().getString("product_id");
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id);
arrayList = productBackgroundTask.getList();
String price = arrayList.get(position).getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
// price.setText(price);
}else {
Log.i(TAG, "getArgument is null");
}
return view;
}
}
this is task to get arraylist using volley
public class ProductBackgroundTask {
private Context context;
ArrayList<ProductItem> arrayList = new ArrayList<>();
String json_url = "phpfile.php";
private String product_id;
public ProductBackgroundTask(Context context, String product_id) {
this.context = context;
this.product_id = product_id;
}
public ArrayList<ProductItem> getList(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
return arrayList;
}
}
and this is class of array list
public class ProductItem {
private String Price,Date;
private int ProductId;
public ProductItem(String Price, String Date, int ProductId){
this.setPrice(Price);
this.setDate(Date);
this.setProductId(ProductId);
}
public int getProductId() {
return ProductId;
}
public void setProductId(int productId) {
ProductId = productId;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
Date = date;
}
Clearly in your oncreate you haven’t initialized the product item and you cannot parse the complete list.You can try two to solve this
1.Pass specific item number instead of position i.e
say if you want to show 4th item then position=3
2.Or write a loop like this to parse entire arrayList like this
for(ProductItem productItem:arrayList){
String price = productItem.getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
price.setText(price);
}
Mistake you're doing is that in the MainActivityFragment your trying to assign the value to the arrayList even before the data is added to the arrayList in the ProductBackgroundTask-getList. That's the reason you are getting the list null all the time. Try to use interfaces.
1.Make your MainActivityFragment implement the interface.
2.Set the value to the interface method once you get the data from the server.
3.Get the data in the MainActivityFragment inside interface method and do all the operation you're doing inside the onCreateView method.
Now your arraylist will have the data whatever you received from the server.
Below is the link for the example on interfaces if you haven't used them before. He is doing exactly as your requirement.
https://www.justinmccandless.com/post/setting-up-a-callback-function-in-android/
Allow me. The arrayList that you return from getList isn't populated at the time you call String price = arrayList.get(position).getPrice();. The server call using volley takes some time to process and that's when the onResponse gets called. This happens AFTER you've returned the arrayList which is in fact empty.
The sequence of events is as follows.
• Call to arrayList = productBackgroundTask.getList(); which returns an empty ArrayList.
• String price = arrayList.get(position).getPrice();
Now after a while..
• onResponse inside getList() gets called.
Do you now see why it's empty?
Simple Solution: • Define a simple interface ProductListener alongside ProductBackgroundTask. (With only a single abstract method onProducts).
• Instantiate it inside the Fragment's onCreateView using an anonymous class and pass it to the constructor of ProductListener to save it for later use. Do whatever you want to do with the products inside the onProducts method. (Since that will be called with the actual data)
• Call its onProducts method with the data that's parsed and fetched inside the onResponse method.
ProductBackgroundTask code:
public class ProductBackgroundTask {
private Context context;
// I removed the instance ArrayList since that can be made
// local.
// Here, we add a reference to our callback interface as we can use it later.
private ProductListener listener;
String json_url = "http://192.168.43.55/android/v1/productList.php";
private String product_id;
// Instantiate this class using an additional listener argument
// which would be a concrete implementation of our interface.
public ProductBackgroundTask(Context context, String product_id, ProductListener listener) {
this.context = context;
this.product_id = product_id;
this.listener = listener;
}
// getList should not return anything,
// so I keep the return as void.
public void getList() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
ArrayList<ProductItem> arrayList = new ArrayList<>();
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
// Notice this line here, this is what
// calls the callback with the products.
listener.onProducts(arrayList);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
}
}
// Callback interface, we would need a concrete implementation
// of this and pass that to the constructor of ProductBackgroundTask.
interface ProductListener {
void onProducts(ArrayList<ProductItem> products);
}
The code inside onCreateView:
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id, new ProductListener() {
// This method will be called with the needed products.
// Give an anonymous class implementation of our interface
// right here since we won't be using it anymore.
public void onProducts(ArrayList<ProductItem> products) {
// Get the price you want.
String str = arrayList.get(0).getPrice();
// Use str wherever necessary. Use the UI thread here if you need
// to change any visible elements on the screen.
}
});
// Simply call this method to get the ball rolling.
productBackgroundTask.getList();
This is a concrete implementation of the this answer and you won't be changing much code.
I want to print an ArrayList. I have receive value arraylist from class AsyncTask, in MainActivity, I have value ArrayList, but when I print ArrayList, my app is not working. Please help me!
MainActivity
{
executeLoadProduct();
arraylistgroup = new ArrayList<String>();
arraylistgroup=TaskLoadProductGroup.getvaluearraylist();
String[] mStringArray = new String[arraylistgroup.size()];
mStringArray = arraylistgroup.toArray(mStringArray);
for (int i = 0; i < mStringArray.length; i++) {
System.out.println("string is2" + (String) mStringArray[i]);
}
executeLoadProduct
private void executeLoadProduct() {
// execute task load product
loadProductGroup = new TaskLoadProductGroup(MainActivity.this);
loadProductGroup.execute();
}
AsyncTask
public class TaskLoadProductGroup extends AsyncTask<String, Void, ArrayList<String>> {
private ActionBarActivity actionBarActivity;
private Context context;
private static ArrayList<String> arrayListgroup;
public TaskLoadProductGroup(ActionBarActivity actionBarActivity) {
this.actionBarActivity = actionBarActivity;
this.context = actionBarActivity.getApplicationContext();
}
#Override
protected void onPreExecute() {
///show progress loading
super.onPreExecute();
}
#Override
protected ArrayList<String> doInBackground(String... url) {
ArrayList<String> listProductgroup = null;
try {
Server server = new Server();
ResListProduct resListProduct = server.getListProducts(context);
//init list item for listview home product
listProductgroup = initItemProduct(resListProduct);
} catch (Exception e) {
}
return listProductgroup;
}
public static ArrayList<String> initItemProduct(ResListProduct rsProduct) {
List<GroupProduct> groups = rsProduct.getGroups();
arrayListgroup = new ArrayList<String>();
for (GroupProduct group : groups) {
// add header group
String s = group.getName();
arrayListgroup.add(s);
}
getvaluearraylist();
// getVarialty();
return arrayListgroup;
}
public static ArrayList<String> getvaluearraylist()
{
return arrayListgroup;
}
#Override
protected void onPostExecute(ArrayList<String> listProductgroup) {
super.onPostExecute(listProductgroup);
}
}
I couldn't identify why are you doing so complex code to print the ArrayList. You can just print that inside onPostExecute method like this,
#Override
protected void onPostExecute(ArrayList<String> listProductgroup) {
super.onPostExecute(listProductgroup);
for (String value : listProductgroup){
Log.d("myTag", value);
}
}
OR
Use loadProductGroup.execute().get() method, but remember this will freeze your UI.
I have an application that does some long calculations, and I would like to show a progress dialog while this is done. So far I have found that I could do this with threads/handlers, but didn't work, and then I found out about the AsyncTask.
In my application I use maps with markers on it, and I have implemented the onTap function to call a method that I have defined. The method creates a dialog with Yes/No buttons, and I would like to call an AsyncTask if Yes is clicked. My question is how to pass an ArrayList<String> to the AsyncTask (and work with it there), and how to get back a new ArrayList<String> like a result from the AsyncTask?
The code of the method looks like this:
String curloc = current.toString();
String itemdesc = item.mDescription;
ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);
ArrayList<String> result = new ArrayList<String>();
new calc_stanica().execute(passing,result);
String minim = result.get(0);
int min = Integer.parseInt(minim);
String glons = result.get(1);
String glats = result.get(2);
double glon = Double.parseDouble(glons);
double glat = Double.parseDouble(glats);
GeoPoint g = new GeoPoint(glon, glat);
String korisni_linii = result.get(3);
So, as you see, I would like to send the string array list "passing" to the AsyncTask, and to get the "result" string array list back from it. And the calc_stanica AssycTask class looks like this:
public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(baraj_mapa.this);
dialog.setTitle("Calculating...");
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
protected ArrayList<String> doInBackground(ArrayList<String>... passing) {
//Some calculations...
return something; //???
}
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
So my question is how to get the elements of the "passing" array list in the AsyncTask doInBackground method (and use them there), and how to return an array list to use in the main method (the "result" array list)?
Change your method to look like this:
String curloc = current.toString();
String itemdesc = item.mDescription;
ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);
new calc_stanica().execute(passing); //no need to pass in result list
And change your async task implementation
public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(baraj_mapa.this);
dialog.setTitle("Calculating...");
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
protected ArrayList<String> doInBackground(ArrayList<String>... passing) {
ArrayList<String> result = new ArrayList<String>();
ArrayList<String> passed = passing[0]; //get passed arraylist
//Some calculations...
return result; //return result
}
protected void onPostExecute(ArrayList<String> result) {
dialog.dismiss();
String minim = result.get(0);
int min = Integer.parseInt(minim);
String glons = result.get(1);
String glats = result.get(2);
double glon = Double.parseDouble(glons);
double glat = Double.parseDouble(glats);
GeoPoint g = new GeoPoint(glon, glat);
String korisni_linii = result.get(3);
}
UPD:
If you want to have access to the task starting context, the easiest way would be to override onPostExecute in place:
new calc_stanica() {
protected void onPostExecute(ArrayList<String> result) {
// here you have access to the context in which execute was called in first place.
// You'll have to mark all the local variables final though..
}
}.execute(passing);
Why would you pass an ArrayList??
It should be possible to just call execute with the params directly:
String curloc = current.toString();
String itemdesc = item.mDescription;
new calc_stanica().execute(itemdesc, curloc)
That how varrargs work, right?
Making an ArrayList to pass the variable is double work.
I sort of agree with leander on this one.
call:
new calc_stanica().execute(stringList.toArray(new String[stringList.size()]));
task:
public class calc_stanica extends AsyncTask<String, Void, ArrayList<String>> {
#Override
protected ArrayList<String> doInBackground(String... args) {
...
}
#Override
protected void onPostExecute(ArrayList<String> result) {
... //do something with the result list here
}
}
Or you could just make the result list a class parameter and replace the ArrayList with a boolean (success/failure);
public class calc_stanica extends AsyncTask<String, Void, Boolean> {
private List<String> resultList;
#Override
protected boolean doInBackground(String... args) {
...
}
#Override
protected void onPostExecute(boolean success) {
... //if successfull, do something with the result list here
}
}
I dont do it like this. I find it easier to overload the constructor of the asychtask class ..
public class calc_stanica extends AsyncTask>
String String mWhateveryouwantToPass;
public calc_stanica( String whateveryouwantToPass)
{
this.String mWhateveryouwantToPass = String whateveryouwantToPass;
}
/*Now you can use whateveryouwantToPass in the entire asynchTask ... you could pass in a context to your activity and try that too.*/ ... ...
You can receive returning results like that:
AsyncTask class
#Override
protected Boolean doInBackground(Void... params) {
if (host.isEmpty() || dbName.isEmpty() || user.isEmpty() || pass.isEmpty() || port.isEmpty()) {
try {
throw new SQLException("Database credentials missing");
} catch (SQLException e) {
e.printStackTrace();
}
}
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
this.conn = DriverManager.getConnection(this.host + ':' + this.port + '/' + this.dbName, this.user, this.pass);
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
receiving class:
_store.execute();
boolean result =_store.get();
Hoping it will help.