setText of TextView on Async Task complete - android

I want to return a specific string using ksoap2 web service in my android app.
Web service is returning the correct value but the set text is not getting updated once the task is complete. I need to do something (like trying to open the navigation drawer) then its getting updated. Any ideas??
My code is as follows
// Calling the async class
protected void onResume() {
try {
super.onResume();
new RetrieveTimeWS().execute();
}
catch (Exception e)
{
Log.e("Current Time", e.getMessage());
}
}
Following is the Async Task
class RetrieveTimeWS extends AsyncTask<Void, Void, String> {
protected String doInBackground(Void... params) {
String datetime = "";
try {
TextView TVcurrentTime = (TextView) findViewById(R.id.DateTimeNow);
TVcurrentTime.setText("Loading...");
datetime = getDateTimeClass.getDateTime();
TVcurrentTime.setText(datetime);
} catch (Exception e) {
Log.e("Async Task - GetDateTime ", e.getMessage());
}
return datetime;
}
}
The text field shows "Loading..." only till I touch any component on the screen. How can i change the textview to the required string after the web service returns the text.
Thanks in advance.
Laks.

You can't interact with UI not from UI thread. AsyncTask has onPreExecute and PostExecute methods which called from UI thread and you can change UI in it.
class RetrieveTimeWS extends AsyncTask<Void, Void, String> {
TextView TVcurrentTime = (TextView) findViewById(R.id.DateTimeNow);
Exception e;
#Override
protected void onPreExecute() {
super.onPreExecute();
TVcurrentTime.setText("Loading...");
}
protected String doInBackground(Void... params) {
String datetime = "";
try {
datetime = getDateTimeClass.getDateTime();
} catch (Exception e) {
this.e = e;
Log.e("Async Task - GetDateTime ", e.getMessage());
}
return datetime;
}
#Override
protected void onPostExecute(final String s) {
super.onPostExecute(s);
if (e != null) {
TVcurrentTime.setText(s);
}
}
}

You can not do any UI work in background thread. Do it in onPostExecute() method.
This method runs on main thread. So, you can set text in this method.

Related

doInBackground is not getting called sometimes Android

In my application, there are multiple asynctasks. Please let me know why doInBackground of an asynctask sometimes does not getting called. Its onPreExecute method gets called. Is there any issue because of multiple asynctasks or something else?
/* ASync class for test table */
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
If your project has multiple asynctasks you must check that there is a limit of asynctasks that can be executed. When you create a new AsyncTask it will be added on a Pool and will be execute only when is possible.
Check this answer:
Multitasking on android
And the docs: ThreadPoolExecutor
Here is an example on how properly handle multiple AsyncTasks AsyncTaskManager
OnPreExecute() gets called on the UI thread and doInBackground() is called on the background thread.
There is one dedicated background thread for the async task. This behaviour can be changed if you want to.
http://android-er.blogspot.in/2014/04/run-multi-asynctask-as-same-time.html
Now, say you have multiple instances of async task and I'm assuming you are calling execute() to run the async tasks. This will trigger all the preExecute immediately since UI thread is free but for the doInBackground it will triggered one by one. Hence it may take some time for the next async task to start.
doInBackground should run on a loop using a Boolean to check before execution. Before your Task is being executed, set a global boolean (may be true/false) depends on which you prefer and values add on thread should call runOnUiThread.
startExect = true;
new TestAsynch().execute();
then change this
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
to this
public class TestAsynch extends AsyncTask<String, Void, String> {
String result1 = null;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
result1=API_Manager.getInstance().sendTestData(userName);
while (startExecute) {
Thread exe = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5);
}
catch( Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if(result1 != null) {
// save in db
}
}
});
}
}); exe.start();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}

How to update TextView from AsynkTask?

This is my code: (Some random text to complete question osdifhgsoid hgodfhgo hsdhoigifdshgnvfa oidvojd nobndisfn vbjobsf).
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x)
{
textIn.setText("shit! " + x.toString());
}
long i = 10;
return i;
}
}
(Some random text again to complete question(stupid system) dpfgojd ipgsdigjsidoignsdog
public void Listen(){
int count = 0;
TextView msg = MyActivity.msg;
ServerSocket server;
Socket client;
try {
server = new ServerSocket(9797);
Log.d("My log", "server started");
Log.d("My log", "waiting for connnections");
while (started) {
try{
msg.setText("waiting for connection"); <=== here crashing
client = server.accept();
count++;
Log.d("My Log", "Connected");
Log.d("My Log", "aha" + count);
int i = 0;
String data = null;
byte[] bytes = new byte[1024];
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
while (is.available() == 0) {
try{
Thread.sleep(50);
}catch (Exception cc){}
}
is.read(bytes, 0, is.available());
os.write("hala".getBytes());
client.close();
}catch (Exception cc)
{
cc.toString();
}
}
} catch (Exception el) {
el.printStackTrace();
}
}
(Some random text to complete question). Please help
change it via the onPostExecute method!
The purpose of an AsyncTask is to do a long running task in a separate thread and then communicate the result back to the UI thread via onPostExecute().
Also, I'm not sure why you use Long as your return value since you do not seem to be using it. A much better solution would be to have Void as return value and save the exception and use that as an indicator if anything went wrong:
private class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
private Exception exception = null;
#Override
protected Void doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x) {
exception = x;
}
}
#Override
public void onPostExecute(Void result) {
if(exception != null) {
textIn.setText("shit! " + exception.toString());
}
else {
// long running task was completed successfully
}
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed.
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
Good idea would be to return a String in doInBackground(), say exceptionCatched. You can set it to Exception title in catch() block and then in onPostExecuted() just check if(!TextUtils.isEmpty(exceptionCatched)) textIn.setText(exceptionCatched); That's it!
private class DownloadFilesTask extends AsyncTask<Void, Void,Long>{
#Override
protected Long doInBackground(Void... params) {
publishProgress(progress);
//calculate progress and value from your downloading logic
try {
} catch (Exception e) {
return (long) 0;
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//dis method run deafult on UI thread , so every time u publish ur onProgressUpdate will be called and update ur text here
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
if(result==0){
//error occured
}
}
// in case of exception return the result as long value to promt to onPostExceute()
I'm guessing runOnUiThread. You can't update the UI from any other thread than the UI thread.

ProgressDialog Android

I am trying to use ProgressDialog. when i run my app the Progress Dialog box show and disappear after 1 second. I want to show it on completion of my process.. Here is my code:
public class MainActivity extends Activity {
android.view.View.OnClickListener mSearchListenerListener;
private ProgressDialog dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new YourCustomAsyncTask().execute(new String[] {null, null});
}
private class YourCustomAsyncTask extends AsyncTask <String, Void, Void> {
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading....");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show(); //Maybe you should call it in ruinOnUIThread in doInBackGround as suggested from a previous answer
}
protected void doInBackground(String strings) {
try {
// search(strings[0], string[1]);
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
dialog.dismiss();
//result
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
return null;
}
}
}
Updated Question:
#Override
public void onCreate(SQLiteDatabase db) {
mDatabase = db;
Log.i("PATH",""+mDatabase.getPath());
mDatabase.execSQL(FTS_TABLE_CREATE);
loadDictionary();
}
/**
* Starts a thread to load the database table with words
*/
private void loadDictionary() {
new Thread(new Runnable() {
public void run() {
try {
loadWords();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private void loadWords() throws IOException {
Log.d(TAG, "Loading words...");
for(int i=0;i<=25;i++)
{ //***//
final Resources resources = mHelperContext.getResources();
InputStream inputStream = resources.openRawResource(raw_textFiles[i]);
//InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
StringBuilder sb = new StringBuilder();
while ((word = reader.readLine()) != null)
{
sb.append(word);
// Log.i("WORD in Parser", ""+word);
}
String contents = sb.toString();
StringTokenizer st = new StringTokenizer(contents, "||");
while (st.hasMoreElements()) {
String row = st.nextElement().toString();
String title = row.substring(0, row.indexOf("$$$"));
String desc = row.substring(row.indexOf("$$$") + 3);
// Log.i("Strings in Database",""+title+""+desc);
long id = addWord(title,desc);
if (id < 0) {
Log.e(TAG, "unable to add word: " + title);
}
}
} finally {
reader.close();
}
}
Log.d(TAG, "DONE loading words.");
}
I want to show ProgressDialogue box untill all words are not entered in the database. This code is in inner calss which extends SQLITEHELPER. so how to can i use ProgressDialogue in that inner class and run my addWords() method in background.
You cannot have this
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
in your doInBackground().
Progress dialog doesn't take priority when there is some other action being performed on the main UI thread. They are intended only when the actions are done in the background. runonUIthread inside doInBackground will not help you. And this is normal behavior for the progressdialog to be visible only for few seconds.
You have two doInBackground() methods inside your AsyncTask Class. Remove the runOnUiThread() from First doInBackground() and move it to second doInBackground() which has #Override annotation.
I don't know whether you wantedly written two doInBackground() methods or by mistake but it is not good to have such confusion between the Method. Your AsyncTask is not calling the first doInBackground() and it will call doInBackground() which has #Override annotation. So your ProgressDialog is dismissed in 1 second of time as it returns null immediately.

Performing data loading unitl succesfull or user break

In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}

AsyncTask and JSOUP Parsing

so basically im trying to parse some data from website using AsyncTask, i want it to get website url from program, update ui with downloaded data and show progressdialog (spinning wheel) so i figured i need to do it like that: (UPDATE): k now its ok with variables but program force closes anyway
private class backgroundDATA extends AsyncTask<String, Void, Void> {
ProgressDialog dialog;
Document doc;
#Override
protected void onPreExecute() {
dialog = dialog.show(Result.this, " ",
" Loading. Please wait ... ", true);
}
#Override
protected Void doInBackground(String... params) {
try {
doc = Jsoup.connect(params[0]).get();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
Elements maine;
Elements titleJSOUP;
Elements recipeJSOUP;
Elements instructionsJSOUP;
String recipE;
maine = doc.select("div#recipeContent");
titleJSOUP = doc.select("title");
recipeJSOUP = maine.select("ul.recipe");
instructionsJSOUP = maine.select("p.instructions");
recipE = recipeJSOUP.toString();
drinkNameText.setText("THE "
+ Jsoup.parse(titleJSOUP.toString()).text()
);
dontListenText.setText(Jsoup.parse(titleJSOUP.toString()).text()
);
recipeText.setText(prepareDRINK(recipE));
instructionsText.setText(Jsoup.parse(instructionsJSOUP.toString())
.text());
dialog.dismiss();
}
}
Well this is going to cause a NullPointerException for a start...
#Override
protected void onPreExecute() {
dialog = dialog.show(Result.this, " ",
" Loading. Please wait ... ", true);
}
You can't call dialog.show(...) as dialog will be null.
Call the static ProgressDialog.show(...) method instead.

Categories

Resources