runOnUiThread is not running in AsyncTask - android

I'm coding a program which fetches the data from MySql from server (using JSON) and it updates the UI accordingly,
I'm fetching two types of data using AsyncTask from Server
1) Bubble Answers
2) Comments
The parseBubbleAnswers method successfully runs and Updates UI,
but parseComments class which is AsyncTask, and which call parseComments method in doInBackground, is not running runOnUiThread(new Runnable() { run() });
Can anyone help me in solving this
Here is my code :
public class FetchServer extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
String photoId = "1"; // photo id for which the data is fetched
checkBubbleData(photoId); // which call AsyncTask - 2 differnt calls
}
public void checkBubbleData(String photoId)
{
new parseBubbleAnswers().execute(photoId); // to fetch bubble answers
new parseComments().execute(photoId); // to fetch comments
}
class parseBubbleAnswers extends AsyncTask<String, Integer,String>
{
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
Looper.prepare();
parseBubbleAnswers(); // which has runOnUiThread(new Runnable() which updates (successfully !) the UI
return null;
}
}
class parseComments extends AsyncTask<String, Integer,String>
{
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
Looper.prepare();
String parseComReturn = parseComments();
if(parseComReturn=="end")
{
commentBuilder(); // which will update UI after fetch data by parseComments() method
}
}
}
public void commentBuilder()
{
runOnUiThread(new Runnable() // while debugging, it comes here, on Step Over it stick for 2 times and then move at the end of method without error
{
public void run()
{
// update UI code
}
});
}
}

Try this way :
First create one Handler :
Handler mHandler = new Handler();
Change this,
public void commentBuilder()
{
runOnUiThread(new Runnable() // while debugging, it comes here, on Step Over it stick for 2 times and then move at the end of method without error
{
public void run()
{
// update UI code
}
});
}
With,
public void commentBuilder()
{
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (isRunning) {
try {
// Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Write your code here to update the UI.
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
}
Stop thread by this once you are done with UI,
isRunning = false;
EDIT :
Try to Use Async Task in this way :
class parseComments extends AsyncTask<String, Integer,String>
{
protected String doInBackground(String... params) {
String parseComReturn = parseComments();
return parseComReturn;
}
protected void onPostExecute(String result) {
if(result.equals("end"))
{
commentBuilder();
}
}
}
Thanks.

runOnUiThread is a method of Activity, AsyncTask has no reference to Activity.
however, AsyncTask already runs on the UI thread and was designed to do exactly that.
just deal with the UI changes in onPostExecute.

I faced the similar issue.
Just pass the reference of the Activity class to the parseComments class.
class parseComments extends AsyncTask<String, Integer,String>{
Activity activity;
public parseComments(Activity activity){
this.activity = activity;
}
}
After that you can use runOnUiThread as
activity.runOnUiThread(new Runnable(){
#Override
public void run(){
}
});
It will only work with Activity class. Not Context class.

Related

Struggling with upating my UI from Thread

I have tried AsyncTask, Handler, and a simple Thread to achieve what I am trying to do but I just cannot get any of them to work, below is the logic that I need to use to update my UI...
public class GameProcessor extends Thread {
#Override
public void run() {
for (Integer integer : sequence) {
//set button state to pressed
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//set button state to un-pressed
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Please do not respond with, you cannot update the UI from anywhere but the main thread, I already know this and need a solution on how to loop through some values from the backend while updating the UI at the same time. From what I can tell, AsyncTask and Handler will not help much.
Any help will be very appreciated!
If you know about the UI thread, why don't you:
runOnUiThread(new Runnable() {
public void run() {
//set button state to un-pressed or pressed.. or whatever you want..
}
});
I don't understand your problem
Create a member Handler object in your Activity (mHandler). Whenever you want to update your UI from the other thread, call
mHandler.post(new Runnable(){
public void run(){
//update the button state
}
});
The Handler will call this run() method in the UI thread for you.
This is simplified. You will probably want to create your Runnables as member variables so your aren't recreating the same Runnables over and over.
If you want to loop through some valuse, while updating the UI at the same time, then you may consider using AsyncTask and may use this feature:
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
And from :
protected Long doInBackground(URL... urls) {
calculate value
publishProgress(value);
return totalSize;
}
This will keep on updating UI thread with intermediate values you send.
In case you already know this and have tried and it does not solve your purpose, am sorry :)
or you can try this:
public void run() {
Console.post(new Runnable() {
public void run() {
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
}
});
}
In order to update your UI thread you can use the handler. Here's a simple example of using AsyncTask and Handler:
private static final String MESSAGE_KEY = "com.example.mypackage.MSGKEY";
private static final int MESSAGE_AUTHENTICATING = 0;
private static final int MESSAGE_AUTHENTICATED = 1;
/**
* This handler will update UI
*
*/
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.getData().getInt(MESSAGE_KEY)) {
case MESSAGE_AUTHENTICATING:
hashstream_stream.setVisibility(View.GONE);
hashstream_progress.setVisibility(View.VISIBLE);
break;
case MESSAGE_AUTHENTICATED:
hashstream_stream.setVisibility(View.VISIBLE);
hashstream_progress.setVisibility(View.GONE);
break;
default:
break;
}
}
};
/**
* This method should be used to update UI thread.
*
* #param value
*/
private void postMessage(int value) {
Message msgObj = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt(MESSAGE_KEY, value);
msgObj.setData(bundle);
handler.sendMessage(msgObj);
}
/**
* AsyncTask Helper class as network op
*
*
*/
private class StreamHashTagTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//Do actual operation in here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
postMessage(MESSAGE_AUTHENTICATED);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
postMessage(MESSAGE_AUTHENTICATING);
}
/**
* If you need to update progress override onProgressUpdate() method.
* Since I am indeterminate using progress bar as authentication time
* cannot be calculated , I don't need update here
*/
}
Did you try?
instanceOfActivity.runOnUiThread(new Runnable(){
#Override
public void run() {
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
}
});
But in this case, I don't suggest you use an activity in another object.
Please using interface like above:
public interface INotifyChange {
void notify(object value); // Example: void notify(int progress);
}
In your activity where invoke GameProcessor
INotifychange mNotifier;
mNotifier = new INotifyChange() {
#Override
public void notify(object value) {
runOnUiThread(new Runnable(){
#Override
public void run() {
//You can update your UI here.
}
});
}
};
// And your GameProcessor
private INotifyChange mNotifier;
public GameProcessor(INotifyChange aNotifier) {
mNotifier = aNotifier;
}
// Where you want to update UI, please invoke
mNotifier.notify(value);

Two background service android

In my acivity, i need to run two background service.
main background service:
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
return null;
}
}
Second background service.
class mloadingTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return "";
}
protected void onPostExecute(String s) {
pd.dismiss();
}
}
In my onCreate() method I want to call the first background and when it finished loading the second background service starts. Part of my background service is as follows.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
However the second background service doesn't seem to start. i am not getting the a print also. I think I miss a step or android doesn't allow more than one background service in the same activity. A help please.
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();
if(loadTask.getStatus()==AsyncTask.Status.FINISHED){
new mloadingTask().execute(getxml);
System.out.println("getxml: "+getxml);
}
there is a 99% chance that the if() block will never pass.
You first execute the first asyncTask named loadTask and RIGHT after check if it finished.
Small chance that it actually finishes by then.
The easy approach:
Use only one async task. You want to finish asyncTask 1 and then fire asyncTask 2, its exactly the same as having only one asyncTask doing both operations.
class loadingTask extends AsyncTask<Void, Void,Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pd.dismiss();
}
...
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getxml = Util.CallWebService("");
SAXHelper sh = null;
try {
sh = new SAXHelper(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
sh.parseContent("");
return null;
}
}
The difficult approach:
How I solve this kind of thing is(our situation is different, but it should do)
Create an interface, with one method. for example:
public interface OnDataChangedListner {
void dataChanged(Class listener);
}
Then somewhere (i use my repository classes)
write a method to add and remove entires to a list of OnDataChangedListener interfaces
private ArrayList<OnDataChangedListner> mOnDataChangedListners;
public void addOnDataChangedListner(OnDataChangedListner onDataChangedListner){
synchronized (mOnDataChangedListners){
mOnDataChangedListners.add(onDataChangedListner);
}
}
public void removeOnDataChangedListner(OnDataChangedListner onyDataChangedListner){
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener .equals(onDataChangedListner))
it.remove();
}
}
}
}
This might be overkill. But this example should help you with updating the UI while your tasks are running. A free extra! :))
With the above code in place, create an onDataChanged() method in the same class where u defined the add and remove listener methods.
In that code call a handler
// Need handler for callbacks to the UI thread
final static Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mNotifyDataChanged = new Runnable() {
public void run() {
if (mOnDataChangedListners != null){
synchronized (mOnDataChangedListners){
for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
OnDataChangedListner listener = it.next();
if (listener != null)
listener.dataChanged(this.getClass());
else
it.remove();
}
}
}
}
};
/**
* will notify registerred delegates on the main (UI) thread
*/
public void notifyDataChanged(){
mHandler.post(mNotifyDataChanged);
}
Ok, so I ended up giving out an entire sample.
Where you place this code is upto you. But when you call notifyDataChanged() it will fire the handler, which in turn will loop trough all current registered listeners for this class
then in turn it will call the listeners datachanged method.
To make this all work, all you have to do is have a class implement the interface
call addOnDataChangedListener(this);
and implement the method provided in the interface.
Note that this is deffinetly not the easiest way to do things.
I don't know what the easiest way to do what you want is. I never have been in that situation before.
but you can execute the second task in the implemented method. Should work..
AsyncTask is Asynchronous as its name suggest. You need to call your 2nd AsyncTask in onPostExecute of your 1st AsyncTask
OR
Loop and wait till AsyncTask is finished in your activity, but it may take more time and you can get Application Not Responding message.
As soon as you call execute() method, control comes to next statement which loadTask.getStatus(). As task is just started, loadTask.getStatus() will not return FINISH and your 2nd task is never getting executed.

Asynchronous task not show Progress Dialog on click event of button

In my application when i click on Button it sometimes shows the progressdialog and sometimes not show the progressdialog on click of button.
Asynchronous Task code is:
public class LoadData extends AsyncTask<Void, Void, Void>
{
ProgressDialog pd;
#Override
protected void onPreExecute()
{
pd = ProgressDialog.show(MainActivity.this, "", "Loading...");
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
LoadActivities(); // function to load data from url
}
});
return null;
}
#Override
protected void onPostExecute(Void unused)
{
pd.dismiss();
}
}
and on button click event call this as:
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new LoadMoreData().execute(null);
}
});
the wrong think you are doing is that in doInBackground you use runOnUiThreade . just remove that from your code . It solves your problem.
never use any thread in doInBackground.
Why you have taken run method again in doInBackground, doInBackground method performs computation on a background thread, so no need to take runOnUiThread
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
LoadActivities(); // function to load data from url
}
});
Just write
protected Boolean doInBackground(final String... args) {
try {
LoadActivities();
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
And also change new LoadMoreData().execute(); don't write null
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new LoadMoreData().execute();
}});
Nirali's answer seems correct, just to make further explaination and some edits.
Progress Dialog will be shown by the time doInBackground method returns value. and in your code it just create another thread, and completes execution, so to display progress dialog by the time LoadActivities exectues, execute this statement in the same thread doInBackground executes, so change to following:
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
MainActivity.this.runOnUiThread(new Runnable() {
LoadActivities(); // function to load data from url
return null;
}

Android: TimerTask scheduled for repetition getting fired only once

Ok this is a very weird problem I am having, and I'm pretty sure that I am messing up somewhere, but I can't quite figure out where.
What I am trying is -
Schedule a Timer to execute a TimerTask every five seconds
The TimerTask in turn executes an AsyncTask (which in this case simple sleeps for a second before returning the static count of the number of AsyncTasks).
Finally, the aforementioned count is updated in the UI.
And of course, the appropriate Handlers and Runnables have been used to post asynchronous messages from other threads to the UI.
This code executes only once. I expect it to fire every 5 seconds. Here's the code.
Note: I had no idea what to do with the Looper. I put it there after trial and error!
public class TimerAsyncMixActivity extends Activity {
public static final String TAG = "TimerAsyncMix";
static int executionCount = 0;
Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(this), 0, 5000);
}
class MyAsyncTask extends AsyncTask<String, Void, Integer>{
#Override
protected Integer doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ++executionCount;
}
#Override
protected void onPostExecute(Integer result) {
mHandler.post(new UpdateUiThread(TimerAsyncMixActivity.this, result));
super.onPostExecute(result);
}
}
}
class MyTimerTask extends TimerTask{
private TimerAsyncMixActivity tma;
public MyTimerTask(TimerAsyncMixActivity tma) {
this.tma = tma;
}
#Override
public void run() {
Looper.prepare();
Log.d(TimerAsyncMixActivity.TAG, "Timer task fired");
tma.new MyAsyncTask().execute();
Looper.loop();
Looper.myLooper().quit();
}
}
class UpdateUiThread implements Runnable{
int displayCount;
TimerAsyncMixActivity tma;
public UpdateUiThread(TimerAsyncMixActivity tma, int i) {
this.displayCount = i;
this.tma = tma;
}
#Override
public void run() {
TextView tv = (TextView) tma.findViewById(R.id.tvDisplay);
tv.setText("Execution count is : "+displayCount);
}
Can anyone point me to what I'm doing wrong?
techie, this is how I implemented similar things. I'm won't claim that this is the best way, but it has worked for me and doesn't look too bad.
I have the following code in my activity. I create an async task when the activity starts and I stop it onPause. The AsyncTask does whatever it needs to do, and updates the UI on onProgressUpdate() (which is run on the UI thread, so there's no need to use a Handler).
private Task task;
#Override
protected void onPause() {
task.stop();
task = null;
}
#Override
protected void onResume() {
task = new Task();
task.execute();
}
private class Task extends AsyncTask<Void, String, Void> {
private boolean running = true;
#Override
protected Void doInBackground(Void... params) {
while( running ) {
//fetch data from server;
this.publishProgress("updated json");
Thread.sleep(5000); // removed try/catch for readability
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if( ! running ) {
return;
}
String json = values[0];
//update views directly, as this is run on the UI thread.
//textView.setText(json);
}
public void stop() {
running = false;
}
}
Do not use a timer. If your phone goes to sleep, the timer is suspended too. Use AlarmManager.

Show Dialog After Thread is Finish

I want show dialog after finish Thread.
In thread I am changing TextView's Value like as 0 to 100...
When TextView Value is reach 100 then i want to show dialog..
What i do for it.
Thanks in advance...
Code Snippet:
final Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
synchronized (this)
{
try
{
for(int i=0 ; i<speed; i++)
{
final int value=i+1;
wait(3000/speed);
Test.this.runOnUiThread(new Runnable() {#Override public void run()
{
accText.setText(String.valueOf(value));
}});
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread.start();
this is asyntask code snippet...
class setTextBackgroundTask extends AsyncTask<String , Integer, Void>
{
#Override
protected void onPreExecute()
{
}
#Override
protected Void doInBackground(String... params)
{
Thread th = new Thread();
int value;
for(int i=0 ; i<speed; i++)
{
value=i+1;
publishProgress(value);
try {
th.sleep(3000/speed);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values)
{
accText.setText(String.valueOf(values[0]));
System.out.println("Value=="+values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result)
{
showShareDialog();
}
}
This document explains how you can create dialogs.
Please note that you will have to do any dialog creation code on the UI thread.
You already have code that runs something on the UI thread, just do that outside the loop,but with the dialog creation code inside.
You should use AsyncTask: subclass AsyncTask, override doInBackground() to execute your time consuming action on another thread, and then override onPostExecute() to show your dialog.
Note that you cannot change UI elements from a non-UI (background) thread. AsyncTask takes care of that for you: it calls doInBackground() on a new thread and then calls onPostExecute() on the UI thread as soon as the background task is complete.

Categories

Resources