android asynctask edittext - android

I have a piece of code that querys my webserver xml parses the data that comes back and fills textfields on my GUi with the relevant data. Before i had this within my oncreate function and the code worked fine. However i wanted to show a loading dialogue to the user so i moved the web server and xml parsing operatons to an asynctask. The problem rises now when i go to populate my GUI text fields with my parsed data and i get an error thrown. Can anyone see what i am doing wrong
new BackgroundAsyncTask().execute(); /// called from the oncreate function
and my background task code is as follows
public class BackgroundAsyncTask extends
AsyncTask<Void, Integer, Void> {
int myProgress;
#Override
protected void onPostExecute(Void result) {
MyDialog.dismiss();
}
#Override
protected void onPreExecute() {
MyDialog = ProgressDialog.show(attraction_more_info.this, " " , " Loading. Please wait ... ", true);
}
#Override
protected Void doInBackground(Void... params) {
xml query and parse stuff on here ...
// Populate page now
TextView titlefield = (TextView) findViewById(R.id.att_title);
TextView add1field = (TextView) findViewById(R.id.att_address1);
TextView add2field = (TextView) findViewById(R.id.att_address2);
TextView townfield = (TextView) findViewById(R.id.att_town);
TextView postcodefield = (TextView) findViewById(R.id.att_postcode);
TextView phonefield = (TextView) findViewById(R.id.att_phone);
WebView webview = (WebView) findViewById(R.id.webview1);
MY ERRORS START HERE
titlefield.setText(attraction_name);
add1field.setText(attraction_address1);
add2field.setText(attraction_address2);
townfield.setText(attraction_town);
postcodefield.setText(attraction_postcode);
phonefield.setText(attraction_phone);
webview.loadData(attraction_description, "text/html", null);
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
}
}
Can anyone help me out?

You can't update UI elements from a non-UI thread. Try moving all the setText() calls and webview.loadData() to onPostExecute()
you'll have to save the query results in the class object to do that

Try this,
add1field.post(new Runnable() {
public void run() {
add1field.setText(attraction_address1);
}
});

Related

Cannot pass values to an AsyncTask in Android

I am using an AsyncTask in an activity.
here is my code
public class MyActivity extends AppCompatActivity {
EditText editUserNameLogin;
EditText editPassLogin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
//ButterKnife.bind(this);
editUserNameLogin = (EditText) findViewById(R.id.input_username_login);
editPassLogin = (EditText) findViewById(R.id.input_password_login);
}
public class AsyncTaskClass extends AsyncTask<String, String, String> {
String strUserName = editUserNameLogin.getText().toString();
String passLogin = editPassLogin.getText().toString();
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(String r) {
}
}
but in doInBackground can't get values passLogin or strUserName
(Toast.makeText(MyActivity.this, passLogin,) don't show any text)
Try and execute AsyncTaskClass in onCreate
new AsyncTaskClass().execute(); //use this method and call this in onCreate
Try this one, inside onCreate
String response="checking";
new AsyncTaskClass().execute(response);
then create inner class AsyncTaskClass,
private class AsyncTaskClass extends AsyncTask<String,Void,String > {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... strings) {
String respose1 = strings[0];
return respose1;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);}
}
You can not perform UI operation inside background AsyncTask doInBackground method because AsyncTask not work with current UI thread, its create new thread while you initialize and execute.
Let me explain you in bref.
While activity start its stay with Activity Thread and when you complete activity operation and destroy its completely remove from operation task.
But while you start AsyncTask on Activity its start with individual operation stat that not depends on activity that you start, so if you perform UI operation in doInBackground method and in case Activity destroyed and you working on UI that already destroyed by activity and UI cannot get reference, its generate an exception. So it's necessary to work with current activity thread not another background thread.
There are many case that you can pass data inside AsyncTask, i'm comfortable with below operation, it can help you also.
// Pass data to AsyncTask comma separated values
new MyBackgroundTask().execute("Hello there!","How are you?");
private class MyBackgroundTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... strings) {
String message1 = strings[0];
String message2 = strings[1];
Log.d("_TAG_", "First String: " + message1);
Log.d("_TAG_", "Second String: " + message2);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
For more information read Android Official Documents AsyncTask Developer Guides
You cant show ui operations like toast in doInBackground if you still want to do that then use this code to display toast while in doInBackground
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
}
});
and also you need to call yourAsyncTaskObject.execute to start asynctask
I have no idea what exactly you want to achieve by such behavior.
But i am pointing out some point here . First of all you can not access any UI element in background thread .
#Override
protected String doInBackground(String... params) {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
The above code is not going to work as doInBackground runs asynchronously separate from UI thread.
If you want to show a toast on AsyncTask started then do it in onPreExecute or after execution do it in onPostExecute.
#Override
protected void onPreExecute() {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
And as i see you never execute the AsyncTask then how are you expecting anything from it. Do call execute().
new AsyncTaskClass().execute();
For more on AsyncTask read AsyncTask.
Try the following:
#Override
protected String doInBackground(String... params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MyActivity.this, passLogin, Toast.LENGTH_SHORT).show();
}
});
}
AsyncTask enables proper and easy use of the UI thread. This class
allows you to perform background operations and publish results on the
UI thread without having to manipulate threads and/or handlers.
new AsyncTaskClass("SEND STRING").execute();
You can pass this Your Value this way
private class AsyncTaskClass extends AsyncTask<String, String, String> {
String strRESPONSE="";
public MyAsyncTask(String str_GET) {
this.strRESPONSE=str_GET; // print "SEND STRING"
}
}

Asynctask inner class not updating UI textview

I have the following code which should update UI textview on Asynctask:
public class HelloWorldActivity extends Activity
{
private static TextView txtview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtview = (TextView) findViewById(R.id.mainview);
}
private static class SimpleTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... res) {
try {
Thread.sleep(1500);
} catch(InterruptedException exception) {
Thread.currentThread().interrupt();
}
return null;
}
#Override
protected void onPostExecute(Void params) {
txtview.setText("Hola Mundo");
}
}
}
Particularly I'm triying to change Hello World to Hola Mundo after 1,5 seconds passed. The problem is that while running the app the text still is Hello World and doesn't change. I get no error of any sort. I have even set txtview value outside onCreate method to avoid any access problems (or so I think).
If after txtview = (TextView) findViewById(R.id.mainview); I do txtview.setText("Hola Mundo"); then it works flawlessly.
What could be the problem?
Forget to execute AsyncTask by calling AsyncTask.execute() method. do it as by adding following lines in onCreate method after initializing txtview TextView object:
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();
You have not called ASyncTask, execute it like this after initializing TextView:
txtview = (TextView) findViewById(R.id.mainview);
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();
Hope is what you want.
Currently you are forget to call AsyncTask.
But i think it is a bad practice to use AsyncTask & Thread.sleep() to update UI .
ou can simply do it with Handler.
Runnable updateUI;
Handler h = new Handler();
updateUI=new Runnable() {
#Override
public void run() {
txtview.setText("Hola Mundo");
}
};
h.postDelayed(updateUI,1500);

Android Access Activity from Async Class

I want to access activity and set text from async class.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button getBtn = (Button) findViewById(R.id.btn_result);
getBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView txt_res = (TextView)findViewById(R.id.txt_Result);
new GetText(txt_res).execute(); // Async class
}
});
}
}
//Async Class
public class GetText AsyncTask<Void, Void, Void>{
private TextView txt_res;
public GetText (TextView txt_res) {
this.txt_res = txt_res;
}
#Override
protected Void doInBackground(Void... params) {
try {
String Result = GetTextFromDb();
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
try
{
Log.v("Success", "Success"); // I see "Success" at Logcat
txt_res.SetText("Success"); // Textview didn't change
}catch (Exception e) {
Log.v("Error", e.getMessage()); // No error at Logcat
}
}
}
I redefine my question. Textview don't change. Whats my mistake.
I redefine my question again. Textview didn't change at two functions(doInBackground, onPostExecute)
You basically have 2 options. You cannot directly access the main thread from asych obviously, so you must use the proper format.
If the text view needs to be updated after the task finishes, simply do the updating in onPostExecute
If the textview is displaying some intermediate progress, use onProgressUpdate
Edit:
Ok so here is your problem now. With asycn tasks, you must return a value from doInBackground. Change the type to String, and change onPostExecute(String result). Void means you are returning nothing. You will also have to change the second of the three parameters at the top of the async task to string as well.
Also, the method is textview.setText(""); not textview.SetText(""). The latter should not compile

Android AsyncTask

Am i fully utilising my AsyncTask? Can someone correct my codes if it is wrong. I just want to make sure my AsyncTask fully works so i wont get any trouble in the future. I wish to use AsyncTask for all my classes. Is it a good practice?
public class SingleMenuItemActivity extends Activity {
// XML node keys
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_THUMB_URL = "thumb_url";
private ProgressDialog pDialog;
String title;
String artist;
String image_url;
ImageView view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.single_list_item);
new loadSingleView().execute();
view = (ImageView) findViewById(R.id.single_image);
}
public class loadSingleView extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(
SingleMenuItemActivity.this);
pDialog.setMessage("Connecting to Server ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args) {
// updating UI from Background Thread
Intent in = getIntent();
image_url = in.getStringExtra(KEY_THUMB_URL);
title = in.getStringExtra(KEY_TITLE);
artist = in.getStringExtra(KEY_ARTIST);
return null;
}
#Override
protected void onPostExecute(String args) {
// dismiss the dialog after getting all products
ImageLoader imgLoader = new ImageLoader(getApplicationContext());
imgLoader.DisplayImage(image_url, view);
TextView lblName = (TextView) findViewById(R.id.name_title);
TextView lblCost = (TextView) findViewById(R.id.name_artist);
lblName.setText(title);
lblCost.setText(artist);
pDialog.dismiss();
}
}
You cant update the UI from Backgroud thread. For example Use doInBackground() to get data from server.All this process will be done in Background.And onPostExecute is to update the UI after background process is over
For more info Study here
Example1
Example2
You can find many more in Google :)
You have to update the UI from the method onPostExecute(). I like to move my task into their own files. This way we have a separation of concerns which makes it more easier to understand the code. We can do this by using a interface to define a callback method
public class LoadSingleView extends AsyncTask<String, String, String> {
public interface LoadSingleViewHandler {
void onSingleViewLoad(String result);
}
private LoadSingleViewHandler handler;
public LoadSingleView(LoadSingleViewHandler handler) {
this.handler = handler;
}
#Override
protected String doInBackground(String... args) {
// Do operation here and return the result
// Operation is usually some network request
// or something that will take alot of time
}
#Override
protected void onPostExecute(String result) {
handler.onSingleViewLoad(result);
}
}
Now just start the task from the activity and have the activity implement LoadSingleViewHandler interface.
Yes, all UI operations have to be done on the main thread, period. You can download the image you want to display in doInBackground(), update the entire UI in onPostExecute().
Also, it's a good practice to move the AsyncTask out of your activity. It is a little more work, but as the app becomes bigger and more complicated, it will make your life easier. You can use handlers to pass data from AsyncTask to your activities.
Do in background must mainly be used for those tasks that must not be performed on UI threads so Use it for connecting to server(API's) to receive and send data.
Dont use it without necessity...

Refresh Game Score TextView using AsyncTask

I am writing a board game in Android where the UI consists of textViews for the scores (CPUScore and PlayerScore). The problem I have is that the UI does not update the score from its initial value when onCreate is called. I have looked at similar questions and the solution most suggested is to use AsyncTask to update the UI thread in the background. However I did not find a solution that dealt explicitly with how to use textViews in AsyncTask.
Here is my attempt:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//....
setContentView(R.layout.main_layout);
//.....
//------------ textViews declared here don't refresh -------------------
TextView playerScoreForm = (TextView) findViewById(R.id.PlayerTotalScore);
playerScoreForm.setText(Integer.toString(PlayerTotal));
playerScoreForm.invalidate();
TextView CPUScoreForm = (TextView) findViewById(R.id.CPUTotalScore);
CPUScoreForm.setText(Integer.toString(CPUTotal));
CPUScoreForm.invalidate();
//--------------------------------------------------------------------------
//AsyncTask method:
new updatePlayerScore().execute(PlayerTotal);
new updateCPUScore().execute(CPUScoreForm);
}
The AsyncTask subclasses:
private class updatePlayerScore extends AsyncTask<TextView, Void, Void> {
#Override
protected TextView doInBackground(TextView... params) {
// what to put here??
}
return playerScoreForm;
}
#Override
protected void onProgressUpdate(Integer... values) {
//??
}
protected void onPostExecute(Integer result) {
playerScoreForm.setText(Integer.toString(result));
}
}
private class UpdateCPUScore extends AsyncTask<TextView, Integer, Integer> {
// same syntax as updatePlayerScore
}
Question:
how do I transfer the textViews that I declared in the onCreate method to the AsyncTask method? I am stumped. I am fairly new to Android development.
a) I'm pretty sure you shouldn't need to invalidate the TextViews after you set them; Android should do that automagically.
b) In theory you'd set your TextView references to be member variables and then reference them in onPostExecute instead of passing them into doInBackground. doInBackground in turn will take whichever bits of data enable you to calculate the new score. What you would do on doInBackground is whatever action would cause a new score to be calculated. The return value from doInBackground gets passed into onPostExecute. You would then update the TextView (now a member variable) with this data in onPostExecute. Does that make sense? You haven't actually posted any code here that would update those score values.
See here for a quick example.
private TextView myScoreView; //initialized in onCreate as you do above.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//....
setContentView(R.layout.main_layout);
//.....
myScoreView = (TextView) findViewById(R.id.PlayerTotalScore);
myScoreView.setText(Integer.toString(PlayerTotal));
new updatePlayerScore().execute(1,2); //parameters for calculation
}
private class updatePlayerScore extends AsyncTask<Integer, Integer, Integer> {
#Override
protected TextView doInBackground(Integer... params) {
int score = params[0] + 2 * params[1];
return score;
}
#Override
protected void onProgressUpdate(Integer... values) {
//if you want to provide some indication in the UI that calculation
//is happening, like moving a progress bar, that's what you'd do here.
}
#Override
protected void onPostExecute(Integer scoreCalculationResult) {
myScoreView.setText(Integer.toString(scoreCalculationResult));
}
}
Edit: If you don't want to do the calculation logic in doInBackgroundThread, you probably just want to use:
runOnUiThread(new Runnable(){
#Override
public void run(){
myScoreView.setText(PlayerScoreValue);
}
});
Or:
myScoreView.post(new Runnable(){
#Override
public void run(){
myScoreView.setText(PlayerScoreValue);
}
});
You can pass the TextView in the constructor of the AsyncTask and update it from the onPostExecute method
private class updatePlayerScore extends AsyncTask<Void, Void, Integer> {
private TextView view;
public updatePlayerScore(TextView textView){
this.view = textView;
}
#Override
protected Integer doInBackground(Void... params) {
int score = 0;
//do you calculation the
return score;
}
protected void onPostExecute(Integer result) {
view.setText(Integer.toString(result));
}
}
note: if you Activity configuration change for any reason i.e the user rotate the device and the you AsyncTask hasn't finish it task the update of you TextView will not be updated so you should retain an instance of you AsyncTask and update the the TextView

Categories

Resources