So i'm trying to call a string, the call:
EditText EditTextSearch = (EditText)findViewById(R.id.editText1);
if(!isEmpty(EditTextSearch)){
Toast.makeText(this, "Getting Information", Toast.LENGTH_LONG).show();
Log.v("checkText =>", EditTextSearch.getText().toString());
getComics getComicInfo = new getComics(EditTextSearch.getText().toString(), 1);
getComicInfo.execute();
}
after that i'm calling asynctask
class getComics extends AsyncTask<Void, Void, Void>{
private String comicName;
private String comicNameForSearch;
private int getOptionNumber;
String jsonString = "";
String result = "";
getComics(String comicName, int getOptionNumber)
{
Log.v("Check name A =>", comicName); //show name
}
//set option for search
public void SetOptionNumber(int getOptionNumber){
this.getOptionNumber = getOptionNumber;
}
public int getOptionNumber(){
return this.getOptionNumber;
}
//the data that the user searching for
public void SetComicName(String comicName){
this.comicName = comicName;
}
public String GetComicName(){
return this.comicName;
}
/*the request to the API, include fixing space and getting information about the main object, data, later on i'll call
the object I got to show the the results array */
#Override
protected Void doInBackground(Void... params) {
Log.v("is callingB =>", "Yes");
comicNameForSearch = GetComicName();
Log.v("check name=>", comicNameForSearch ); // make the app crash
anyway, if i'm trying to Log.v, the app crash, what make me think that the DoInBackground doesn't recive the comicName for some reason, guess it because of the execute way, any ideas?
edit: first time going with API so sorry if any dumb problems
the error message:Caused by: java.lang.nullPointerException: println needs a message
You are missing Assinging the value in Constructor so which results in a NullPointerException
Change this
getComics(String comicName, int getOptionNumber)
{
Log.v("Check name A =>", comicName); //show name
}
into
getComics(String comicName, int getOptionNumber)
{
this.comicName = comicName;
this.getOptionNumber = getOptionNumber;
Log.v("Check name A =>", comicName); //show name
}
Your app is getting exception because your data in Asynctask is null which you are printing and passing in doInBackground.
Change you Asynctask to this:
class getComics extends AsyncTask<Void, Void, Void>{
private String comicName;
private String comicNameForSearch;
private int getOptionNumber;
String jsonString = "";
String result = "";
getComics(String comicName, int getOptionNumber)
{
this.comicName = comicName;
this.getOptionNumber = getOptionNumber;
Log.v("Check name A =>", comicName); //show name
}
//set option for search
public void SetOptionNumber(int getOptionNumber){
this.getOptionNumber = getOptionNumber;
}
public int getOptionNumber(){
return this.getOptionNumber;
}
//the data that the user searching for
public void SetComicName(String comicName){
this.comicName = comicName;
}
public String GetComicName(){
return this.comicName;
}
/*the request to the API, include fixing space and getting information about the main object, data, later on i'll call
the object I got to show the the results array */
#Override
protected Void doInBackground(Void... params) {
Log.v("is callingB =>", "Yes");
comicNameForSearch = GetComicName();
Log.v("check name=>", comicNameForSearch ); // make the app crash
And Another way is by calling the setter method you have made inside your class like this:
getComics getComicInfo = new getComics(EditTextSearch.getText().toString(), 1);
getComicInfo .SetComicName(EditTextSearch.getText().toString());
getComicInfo .SetOptionNumber(1);
getComicInfo.execute();
Related
i'm creating an app that grabs list of playlists on YouTube. It used to be a list of videos, but i've changed the code and now it did not let me override that method.
My understanding is that i should change the "extends AsyncTask" with the new Playlist value instead of Video as it was before, but it still did not work.
it was:
public abstract class GetPlaylistAsyncTask extends AsyncTask<String, Void, Pair<String, List<Video>>> {
and now is:
public abstract class GetPlaylistAsyncTask extends AsyncTask<String, Void, Pair<String, List<Playlist>>> {
This is where is the error:
mPlaylist = new Playlist(mPlaylistId);
initAdapter(mPlaylist);
new GetPlaylistAsyncTask(mYouTubeDataApi, mTitle, mSearchQuery) {
#Override
public void onPostExecute(Pair<String, List<Playlist>> result) {
handleGetPlaylistResult(mPlaylist, result);
}
}.execute(mPlaylist.playlistId, mPlaylist.getNextPageToken());
And this is the AsyncTask:
public abstract class GetPlaylistAsyncTask extends AsyncTask<String, Void, Pair<String, List<Playlist>>> {
private static final String TAG = "GetPlaylistAsyncTask";
private static final Long YOUTUBE_PLAYLIST_MAX_RESULTS = 50L;
private static final String YOUTUBE_VIDEOS_PART = "snippet,contentDetails,statistics"; // video resource properties that the response will include.
private static final String YOUTUBE_VIDEOS_FIELDS = "items(id,snippet(title,description,thumbnails/high),contentDetails/duration,statistics)"; // selector specifying which fields to include in a partial response.
private YouTube mYouTubeDataApi;
private String mTitle;
private String mSearchQuery;
public GetPlaylistAsyncTask(YouTube api, String title, String searchQuery) {
mYouTubeDataApi = api;
mTitle = title;
mSearchQuery = searchQuery;
}
#Override
protected Pair<String, List<Playlist>> doInBackground(String... params) {
SearchListResponse searchResponse;
try {
YouTube.Search.List search = mYouTubeDataApi.search().list("id,snippet");
search.setKey(ApiKey.YOUTUBE_API_KEY);
search.setQ(mTitle + " " + mSearchQuery);
search.setType("video");
search.setFields("items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)");
search.setMaxResults(YOUTUBE_PLAYLIST_MAX_RESULTS);
searchResponse = search.execute();
} catch (IOException e) {
e.printStackTrace();
return null;
}
if (searchResponse == null) {
Log.e(TAG, "Failed to get playlist");
return null;
}
ArrayList videoIds = new ArrayList();
for (SearchResult item : searchResponse.getItems()) {
videoIds.add(item.getId().getVideoId());
}
VideoListResponse videoListResponse = null;
try {
videoListResponse = mYouTubeDataApi.videos()
.list(YOUTUBE_VIDEOS_PART)
.setFields(YOUTUBE_VIDEOS_FIELDS)
.setKey(ApiKey.YOUTUBE_API_KEY)
.setId(TextUtils.join(",", videoIds)).execute();
} catch (IOException e) {
e.printStackTrace();
}
return new Pair(searchResponse.getNextPageToken(), videoListResponse.getItems());
}
}
i don't get what is wrong on my code, i'll appreciate if you can point me on the right direction. Thanks in advance!
I've figured it out. The "onPostExecute" takes the object that doInBackground returns, as this post says:
stackoverflow post
Thanks to all for your answers, especially to #Enzokie
Just change public to protected since onPostExecute is not public by design.
#Override
protected void onPostExecute(Pair<String, List<Playlist>> result) {
handleGetPlaylistResult(mPlaylist, result);
}
I can't resolve this error. Please help me. I have this two methods:
public boolean isEmailValid(String email) {
boolean flag;
CharSequence inputStr = email.trim();
Pattern pattern = Pattern.compile(EXPRESSION,
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(inputStr);
if (matcher.matches())
flag = true;
else {
flag = false;
}
return flag;
}
public boolean isFieldsEmpty(String login, String mdp) {
Boolean result = true;
if (login.equals("") || mdp.equals("")) {
result = true;
} else {
result = false;
}
return result;
}
class LoginUser extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute(){
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
prefs = getSharedPreferences("PFE_Prefs",MODE_PRIVATE);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressBar.setVisibility(View.GONE);
switch (s) {
case "Champs_vides":
Toast.makeText(getApplicationContext(), "Merci de bien vouloir remplir tous les champs, svp", Toast.LENGTH_SHORT).show();
EmailEditText.setText("");
MdpEditText.setText("");
break;
case "Email_incorrect":
Toast.makeText(getApplicationContext(),"Merci de bien vouloir verifier votre adresse email, svp", Toast.LENGTH_SHORT ).show();
EmailEditText.setText("");
MdpEditText.setText("");
break;
case "Success": //Appel a l'activité Tableau de bord
Intent toDashBord = new Intent(getApplicationContext(), DashBoardActivity.class);
startActivity(toDashBord);
LoginActivity.this.finish();
break;
case "Echoué" :
Toast.makeText(getApplicationContext(),"Merci de bien vouloir verifier votre connexion, svp", Toast.LENGTH_SHORT ).show();
EmailEditText.setText("");
MdpEditText.setText("");
break;
}
}
And in the method doInBackground:
protected String doInBackground(String... params) {
int success = 0;
String result = "";
JSONObject json ;
WebCalls webCalls = new WebCalls();
JSONObject jsonUser;
User tempUser ;
if (isFieldsEmpty(EmailEditText.getText().toString(),MdpEditText.getText().toString())){
result = "Empty_Field";
return result ;
}else if (!isEmailValid(EmailEditText.getText().toString().trim())){
result = "Wrong_mail";
return result ;
}
return null;
}
My problem is in EmailEditText.getText().toString(), I'm getting the following error:
Method getText() must called from UI thread, currently inferred thread is worker
Call all your getText() functions in onCreate or somewhere before AsyncTask and assign the return values to the public values. So you can reach them.
public String MyeMail;
public String MyMDP;
onCreate()...
{
MyeMail= EmailEditText.getText().toString();
MyMDP = MdpEditText.getText().toString()
.
.
.
}
It doesn't have to be in onCreate but it must be after the user entered the EditText fields. You can do these after a button click maybe. Anyways, now in your AsyncTask's doInBackground:
doInBackground...
{
if (isFieldsEmpty(MyeMail,)) {
result = "Empty_Field";
return result ;
.
.
.
}
So hope it helps! Let me know if it works.
getText() must be called on the main application thread. doInBackground() is being called on a background thread.
Get the values out of the EditText and provide them to the AsyncTask (e.g., via a constructor) before executing the task.
AsyncTask's doInBackground() always runs in a non-UI worker thread which means that you cannot access UI elements like EditText,TextView in doInBackground(). SO, if you want to access these in doInBackground(), then you can either pass those in your AsyncTask's constructor and use them or the best approach would be to pass EmailEditText.getText().toString() and MdpEditText.getText().toString() as params in the execute() method of AsyncTask.
So, let's say if your AsyncTask name is "ProcessTask", then while you start your AsyncTask, write this :
new ProcessTask().execute(EmailEditText.getText().toString(), MdpEditText.getText().toString());
In this case your AsyncTask should change to look like :
class ProcessTask extends AsyncTask<String,Void,Void >{
#Override
protected File doInBackground(String... params) {
String emailEditText = params[0];
String mdpEditText = params[1];
int success = 0;
String result = "";
JSONObject json ;
WebCalls webCalls = new WebCalls();
JSONObject jsonUser;
User tempUser ;
if (isFieldsEmpty(emailEditText,mdpEditText)){
result = "Empty_Field";
return result ;
}else if (!isEmailValid(emailEditText.trim())){
result = "Wrong_mail";
return result ;
}
return null;
}
Your error lies in the method doInBackground()
You are calling 2 objects EmailEditText and MdpEditText which are part of the UI Thread inside another thread.
And hence you are being asked to call "EmailEditText.getText().toString()" from UI thread.
What you are trying to do is'nt exactly clear form the snippets you have posted.
But this example might help:
In your OnCreate() have something like this
protected void onCreate(Bundle savedInstanceState) {
...
String parameters= new String[2];//make this global if you aren't calling your AsyncTask in onCreate()
parameters[1]=EmailEditText.getText().toString();
parameters[2]=MdpEditText.getText().toString();
...
}
and call your AsyncTask like this:
new YourTask().execute(parameters);
while declaration for your AsyncTask would be like this:
private class YourTask extends AsyncTask<String, Void, String> {
...
#Override
protected String doInBackground(String... params) {
String email = params[0];
String mdp= params[1];
int success = 0;
String result = "";
JSONObject json ;
WebCalls webCalls = new WebCalls();
JSONObject jsonUser;
User tempUser ;
if (isFieldsEmpty(email,mdp)){
result = "Empty_Field";
return result ;
}else if (!isEmailValid(email.trim())){
result = "Wrong_mail";
return result ;
}
return null;
}
...
}
Hope this helps!!
I want to check if a user is registered or not in a database, and if it is get the information of the user.
Normally, when I retrieve the information from the server, I put in the Json a variable saying if the user exists or not. Then in onPostExecute(Void result) i treat the Json, so i don't need the AsyncTask to return any value.
Before I was calling the AsyncTask as follows:
task=new isCollectorRegistered();
task.execute();
But now i'm trying a different approach. I want my asynktask to just return a boolean where i called the AsyncTask.
the AsyncTask looks as follows:
public class isCollectorRegistered extends AsyncTask<Void, Void, Void> {
private static final String TAG_SUCCESS = "success";
int TAG_SUCCESS1;
private static final String TAG_COLLECTOR = "collector";
public String collector;
JSONArray USER = null;
JSONObject jObj = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// Checks on the server if collector is registered
try {
jObj = ServerUtilities.UserRegistered(context, collector);
return null;
} finally {
return null;
}
}
#Override
protected void onPostExecute(Void result) {
try {
String success = jObj.getString(TAG_SUCCESS);
Log.d(TAG_COLLECTOR, "Final Info: " + success);
//This if sees if user correct
if (Objects.equals(success, "1")){
//GOOD! THE COLLECTOR EXISTS!!
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG_COLLECTOR, "JSON parsing didn't work");
}
}
}
I have checked several posts, but I still havent found out the way to retrieve the boolean where I call the Asynktask, something like this :
task=new isCollectorRegistered();
task.execute();
boolean UserRegistered = task.result();
What would be the right approach? Any help would be appreciated
To use AsyncTask you must subclass it. AsyncTask uses generics and varargs. The parameters are the following AsyncTask <TypeOfVarArgParams , ProgressValue , ResultValue> .
An AsyncTask is started via the execute() method.
The execute() method calls the doInBackground() and the onPostExecute() method.
TypeOfVarArgParams is passed into the doInBackground() method as input, ProgressValue is used for progress information and ResultValue must be returned from doInBackground() method and is passed to onPostExecute() as a parameter.
In your case you are passing Void to your AsyncTask : isCollectorRegistered extends AsyncTask<Void, Void, Void> so you can't get your result from the thread.
please read this tutorial to a deep understand of the AsyncTask in Android
I think the following is exactly what you were looking for, Alvaro...NOTE: I tweaked your code to make it more sensible, but I tried to stick to as much of your original code as possible...
public class RegisterCollector extends AsyncTask<String, Void, Boolean> {
private static final String TAG_SUCCESS = "success";
private static final String TAG_COLLECTOR = "collector";
int TAG_SUCCESS1;
String[] strArray;
JSONArray USER = null;
JSONObject jObj = null;
public String collector;
private AppCompatActivity mAct; // Just incase you need an Activity Context inside your AsyncTask...
private ProgressDialog progDial;
// Pass data to the AsyncTask class via constructor -> HACK!!
// This is a HACK because you are apparently only suppose to pass data to AsyncTask via the 'execute()' method.
public RegisterCollector (AppCompatActivity mAct, String[] strArray) {
this.mAct = mAct;
this.strArray = strArray;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// AHAH!! - So we do need that Activity Context after all...*TISK* *TISK* # Google **sigh**.
progDial = ProgressDialog.show(mAct, "Please wait...", "Fetching the strawberries & cream", true, false);
}
#Override
protected Boolean doInBackground(String... params) {
// Checks on the server if collector is registered
try {
jObj = ServerUtilities.UserRegistered(context, collector);
return true; // return whatever Boolean you require here.
} finally {
return false; // return whatever Boolean you require here.
}
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progDial.dismiss();
try {
String success = jObj.getString(TAG_SUCCESS);
Log.d(TAG_COLLECTOR, "Final Info: " + success);
// This 'if' block checks if the user is correct...
if (Objects.equals(success, "1")){
//GOOD! THE COLLECTOR EXISTS!!
}
// You can then also use the Boolean result here if you need to...
if (result) {
// GOOD! THE COLLECTOR EXISTS!!
} else {
// Oh my --> We need to try again!! :(
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG_COLLECTOR, "JSON parsing didn't work");
Toast.makeText(mAct, "JSON parsing FAILED - Please try again.", Toast.LENGTH_LONG).show();
}
}
}
...then if you want to use the generated Boolean data outside the AsyncTask class try the following:.
RegisterCollector regisColctr = new RegisterCollector((AppCompatActivity) this, String[] myStrArry);
AsyncTask<String, Void, Boolean> exeRegisColctr = regisColctr.execute("");
Boolean isColctrRegistered = false;
try {
isColctrRegistered = exeRegisColctr.get(); // This is how you FINALLY 'get' the Boolean data outside the AsyncTask...-> VERY IMPORTANT!!
} catch (InterruptedException in) {
in.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
if (isColctrRegistered) {
// Do whatever tasks you need to do here based on the positive (i.e. 'true') AsyncTask Bool result...
} else {
// Do whatever tasks you need to do here based on the negative (i.e. 'false') AsyncTask Bool result...
}
There you go - I think this is what you were looking for (originally). I always use this approach whenever I need Async data externally, and it has yet to fail me....
I'm writing an application that validates login credentials on an external webserver - so I have the basic issue of creating a login screen that when submitted will send an HTTP request to a server in the background and not cause the UI to hang - whilst providing a ProgressDialog to the user.
My problem lies in, I want to write a generic HTTP Request class that extends AsyncTask, so when I call .execute() I will then pass String parameters which may contain something like 'post', and when doInBackground is called this will see the 'post' string and then forward those parameters onto the respective call in my class. Pseudo code would be something like
public class HTTPOperations extends AsyncTask<String, Void, String>
{
doInBackground(String... string1,additionalParams)
{
if string1.equals "post"
response = httpPost(additionalParams)
return response;
}
httpPost(params)
{
// do http post request
}
}
This is all I could think of, other than creating a class for every HTTP Post/GET etc request I wish to make and extending ASyncTask...
Which leads me to my next problem, if the HTTP POST is successful and it returns an authentication token, how do I access this token?
Because new httpOperations.execute(), does not return the string from doInBackground, but a value of type
Sorry if this doesn't make sense, I can't figure this out at all. Please ask for elaboration if you need it. AsyncTask design patterns and ideas are hugely welcomed.
If you are designing a reusable task for something like this, you need to identify a reusable return type. Its a design decision on your part. Ask yourself, "Are my HTTP operations similar in both the mechanisms with which they are called and in which their data is processed?" If so, you can design a single class to do both. If not, you probably need different classes for your different remote operations.
In my personal use, I have an object i attach key value pairs to and the common return type is the HttpEntity. This is the return type for both HTTP Get and Post, and this seems to work ok in my scenarios because i throw exceptions in exceptional HTTP result situations, like 404. Another nice aspect of this setup is that the code to attach parameters to a get or post are fairly similar, so this logic is pretty easy to construct.
An example would be something like this (psuedo):
public interface DownloadCallback {
void onSuccess(String downloadedString);
void onFailure(Exception exception);
}
Then in your code, where you go to do the download:
DownloadCallback dc = new DownloadCallback(){
public void onSuccess(String downloadedString){
Log.d("TEST", "Downloaded the string: "+ downloadedString);
}
public void onFailure(Exception e){
Log.d("TEST", "Download had a serious failure: "+ e.getMessage());
}
}
DownloadAsyncTask dlTask = new DownloadAsyncTask(dc);
Then inside the constructor of DownloadAsyncTask, store the DownloadCallback and, when the download is complete or fails, call the method on the download callback that corresponds to the event. So...
public class DownloadAsyncTask extends AsyncTask <X, Y, Z>(){
DownloadCallback dc = null;
DownloadAsyncTask(DownloadCallback dc){
this.dc = dc;
}
... other stuff ...
protected void onPostExecute(String string){
dc.onSuccess(string);
}
}
I'm going to reiterate that I think for the good of yourself, you should pass back HttpEntities. String may seem like a good idea now, but it really leads to trouble later when you want to do more sophisticated logic behind your http calls. Of course, thats up to you. Hopefully this helps.
suppose the data format with web api is json, my design pattern :
common classes
1.MyAsyncTask : extends AsyncTask
2.BackgroundBase : parameters to server
3.API_Base : parameters from server
4.MyTaskCompleted : callback interface
public class MyAsyncTask<BackgroundClass extends BackgroundBase,APIClass extends API_Base> extends AsyncTask<BackgroundClass, Void, APIClass> {
private ProgressDialog pd ;
private MyTaskCompleted listener;
private Context cxt;
private Class<APIClass> resultType;
private String url;
private int requestCode;
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url){
this.listener = listener;
this.cxt = (Context)listener;
this.requestCode = requestCode;
this.resultType = resultType;
this.url = url;
}
public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url, ProgressDialog pd){
this(listener, resultType, requestCode, url);
this.pd = pd;
this.pd.show();
}
#Override
protected APIClass doInBackground(BackgroundClass... params) {
APIClass result = null;
try {
//do something with url and params, and get data from WebServer api
BackgroundClass oParams = params[0];
String sUrl = url + "?d=" + URLEncoder.encode(oParams.getJSON(), "UTF-8");
String source = "{\"RtnCode\":1, \"ResultA\":\"result aaa\", \"ResultB\":\"result bbb\"}";
//to see progressdialog
Thread.sleep(2000);
result = new com.google.gson.Gson().fromJson(source, resultType);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(APIClass result) {
super.onPostExecute(result);
try {
if(pd != null && pd.isShowing())
pd.dismiss();
API_Base oApi_Base = (API_Base)result;
listener.onMyTaskCompleted(result , this.requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class API_Base {
public int RtnCode;
public String getJSON(Context context) throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
public String toString(){
StringBuilder sb = new StringBuilder();
for (Field field : this.getClass().getFields()) {
try {
field.setAccessible(true);
Object value = field.get(this);
if (value != null) {
sb.append(String.format("%s = %s\n", field.getName(), value));
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
return sb.toString();
}
}
public class BackgroundBase {
public String getJSON() throws Exception
{
return new com.google.gson.Gson().toJson(this);
}
}
public interface MyTaskCompleted {
void onMyTaskCompleted(API_Base oApi_Base, int requestCode) ;
}
example, let's call two api in one activity
assume :
API 1.http://www.google.com/action/a
input params : ActionA
output params : RtnCode, ResultA
API 2.http://www.google.com/action/b
input params : ActionB
output params : RtnCode, ResultB
classes with example :
1.MyActivity : extends Activity and implements MyTaskCompleted
2.MyConfig : utility class, i set requestCode here
3.BackgroundActionA, BackgroundActionB : model classes for api's input params
4.API_ActionA, API_ActionB : model classes for api's output params
public class MyActivity extends Activity implements MyTaskCompleted {
ProgressDialog pd;
Button btnActionA, btnActionB;
TextView txtResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
btnActionA = (Button)findViewById(R.id.btn_actionA);
btnActionB = (Button)findViewById(R.id.btn_actionB);
txtResult = (TextView)findViewById(R.id.txt_result);
btnActionA.setOnClickListener(listener_ActionA);
btnActionB.setOnClickListener(listener_ActionB);
pd = new ProgressDialog(MyActivity.this);
pd.setTitle("Title");
pd.setMessage("Loading");
}
Button.OnClickListener listener_ActionA = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//without ProgressDialog
BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA");
new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this,
API_ActionA.class,
MyConfig.RequestCode_actionA,
"http://www.google.com/action/a").execute(oBackgroundActionA);
}
};
Button.OnClickListener listener_ActionB = new Button.OnClickListener(){
#Override
public void onClick(View v) {
//has ProgressDialog
BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB");
new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this,
API_ActionB.class,
MyConfig.RequestCode_actionB,
"http://www.google.com/action/b",
MyActivity.this.pd).execute(oBackgroundActionB);
}
};
#Override
public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) {
// TODO Auto-generated method stub
if(requestCode == MyConfig.RequestCode_actionA){
API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base;
txtResult.setText(oAPI_ActionA.toString());
}else if(requestCode == MyConfig.RequestCode_actionB){
API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base;
txtResult.setText(oAPI_ActionB.toString());
}
}
}
public class MyConfig {
public static String LogTag = "henrytest";
public static int RequestCode_actionA = 1001;
public static int RequestCode_actionB = 1002;
}
public class BackgroundActionA extends BackgroundBase {
public String ActionA ;
public BackgroundActionA(String actionA){
this.ActionA = actionA;
}
}
public class BackgroundActionB extends BackgroundBase {
public String ActionB;
public BackgroundActionB(String actionB){
this.ActionB = actionB;
}
}
public class API_ActionA extends API_Base {
public String ResultA;
}
public class API_ActionB extends API_Base {
public String ResultB;
}
Advantage with this design pattern :
1.one Advantage for multi api
2.just add model classes for new api, ex: BackgroundActionA and API_ActionA
3.determine which API by different requestCode in callback function : onMyTaskCompleted
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.