I create a class and extend it from view. also implemented the Runnable interface. In the onTouchEvent i call: new Thread(this).start().
This is my class:
public class test extend View interface Runnable{
----some code------
public void onTouchEvent(MotionEvent event){
----somecode------
new thread(this).start();
----somecode------
}
public void run(){
-----somecode-------
invalidate();
-----somecode-------
}
}
but i receive this error:
only the original thread that created a view hierarchy can touch its views
How can i fix this?
Try to use
postInvalidate()
instead of
invalidate()
you need to update UI on UIThread, use
Activity activity = (Activity)getContext();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// update UI here
invalidate();
}
});
You can use handler class to make changes on your UI thread by sending messages.
http://developer.android.com/reference/android/os/Handler.html
Android, Handler messaging
Since you are extending View class which binds to UI-thread, so anything you call in this class will run on the UI-thread. However, if you are using a new thread inside that class, then you may rely on its post(Runnable) method which will guarantee to run on the view's UI-thread. For example:
post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
this will run on UI thread from View class;
post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
Try AsyncTask in android. It start new thread asynchronously and after completion of task it can update current UI without destroying current Activity.
Example Code :
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
// Task which should be completed in background.
return null;
}
protected void onProgressUpdate(Integer... progress) {
// Task which can be done while background process is progressing , such as updatng any UI element of Activity.
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
// Task to do after completion of asynctask.
showDialog("Downloaded " + result + " bytes");
}
}
You may also use runOnUiThread to do your task.
Both ways are very effective in updating UI in current activity.
Useful Link : http://developer.android.com/reference/android/os/AsyncTask.html
http://sharecoding.wordpress.com/2012/05/22/simple-runonuithread-for-update-view-on-android/
Related
Edit: It was suggested that it would be helpful to add my code so, my AsyncTask code is now pasted below...
I'm just learning Android and I have a UI with a few buttons. I want to animate the UI, changing the color of the buttons, in a sequence.
I shouldn't do that from the main thread of course, and it doesn't work anyway. The code manipulating the UI runs but the UI doesn't update until the end of the sequence.
So I created a thread and tried to run through the sequence from a background thread however, I would get an error trying to manipulate the UI components from the background thread. Only the main thread can touch the UI components.
Then I discovered AsyncTask. What I figured was, I could run through the sequence in doInBackground(). Every time I needed to update the UI I'd call publishProgress() which would cause onProgressUpdate() to be called from the main thread so I could access UI components without error.
Every time I call publishProgress() I would follow it with a SystemClock.sleep(500) to let time pass until the next animated UI update.
What I found though was that doInBackground() would run through the 4 UI state changes in about 2 seconds (500 ms each) but the UI would not update with each call to publishProgress(). Instead doInBackground() completes and then onProgressUpdate() is called 4 times in a row.
From the description, publishProgress & onProgressUpdate are designed to update a progress bar as doInBackground cranks through some longish running task so, obviously, onProgressUpdate must execute multiple times before doInBackground completes, right?
Am I missing something?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startGame(View view) {
MyTask task = new MyTask();
task.doInBackground();
}
class MyTask extends AsyncTask<Void,Void,Void> {
private int current_int;
#Override
protected Void doInBackground(Void... voids) {
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
return null;
}
#Override
protected void onProgressUpdate(Void... voids) {
super.onProgressUpdate(voids);
Log.e("onProgressUpdate","Updating button "+this.current_int);
Button btn1 = (Button) findViewById(R.id.button1);
Button btn2 = (Button) findViewById(R.id.button2);
if (this.current_int==1){
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
} else {
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
}
}
}
}
Just for reference : An Asynctask presents a systematic way to transition from main thread (calling thread) to the new thread (called thread). The onPreExecute() and onPostExecute() methods execute on the calling thread and the doInBackground() is the actual method executing on the new thread. Doing UI updates on main thread will hence lead to exception if done from doInBackground() method.
Your core background logic should hence be placed in the doInBackground() method.
If you want to update UI from background thread (Asynctask or otherwise), you can do it using this :
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run()
{
//UI update operations here
}
});
You can use Handler for this,
public class TestClass extends AsyncTask<Void,Void,Void> {
boolean isRunning = true; //set false after executing UI logic.
Handler mHandler = new Handler();
#Override
protected Void doInBackground(Void... params) {
YourFunctionToUpdateUI();
return null;
}
public void YourFunctionToUpdateUI()
{
new Thread(new Runnable() {
#Override
public void run() {
while (isRunning) {
try {
mHandler.post(new Runnable() {
#Override
public void run() {
// your code to update the UI.
}
});
} catch (Exception e) {
//handle exception
}
}
}
}).start();
}
}
I'm an idiot. The problem is, I'm creating an AsyncTask and then calling doInBackground() directly, from my main thread instead of calling execute() which creates the background thread
I am an iOS developer who just recently tried Android development.
In iOS I use Completion Handlers in my codes.
I am wondering if there is an equivalent of it in Android development?
Thank you
If you need it for doing asynchronous operations then look into AsyncTask - this is a class where you implement doInBackground where your long operation is performed and onPostExecute method where code that is suppose to update UI is performed.
Now if you want to pass some special code to your AsyncTask to be performed after long operation you can:
(1) Pass an interface which would be implemented by your Activity/fragment, ex:
// Psedocode to reduce size!
interface MyInterface {
void doWork();
};
class MyAsyncTask extends AsyncTask<Void,Void,Void> {
MyInterface oper;
public MyAsyncTask(MyInterface op) { oper = op; }
// ..
public onPostExecute(Void res) {
oper.doWork(); // you could pass results here
}
}
class MyActivity extends Activity implements MyInterface {
public void doWork() {
// ...
}
public void startWork() {
// execute async on this
new MyAsyncTask(this).execute();
// or execute on anynomous interface implementation
new MyAsyncTask(new MyInterface() {
public void doWork() {
//MyActivity.this.updateUI() ...
}
});
}
};
(2) Use local broadcast receivers, EventBus, but those are more heavy weight solutions.
(3) If you already have some callback interface in you backgroung worker code then you can make it execute on UI thread using this code:
// This can be executed on back thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// do work on UI
}
});
I have an asynctask named myAsync that performs some network operations (fetching data from server, and parsing the json).
I also have a handler created once the activity runs.
I also have a runnable in which i run the asynctask. The reason I am using runnable is because I will be using it inside a Handler's postdelayed method as I want this to be repeated every 1 minute.
Runnable runnable = new Runnable()
{
public void run()
{
new myAsync ().execute();
}
};
Then I am using the above runnable inside my onResume;
#Override
protected void onResume()
{
super.onResume();
handler.postDelayed(runnable, 60000);
}
Whenever I leave the activity, I want the check to stop, so I am calling,
handler.removeCallbacks(runnable);
However, the asynctask keeps on running non stop.
What shall I do ?
The whole point of asynctask is to run a thread on the main thread.
So it does not make sense to run it in Runnable()
What you can do is skip the Runnable and Handler...definitely not needed here. Assuming the AsyncTask is an inner class of your Activity, you can set a member boolean variable and check that in your doInBackground()
public Void doInBackground(Void...params)
{
// this is a boolean variable, declared as an
//Activity member variable, that you set to true when starting the task
while (flag)
{
// run your code
Thread.sleep(60000);
}
return null; // here you can return control to onPostExecute()
// if you need to do anything there
}
This will make the AsyncTask sleep for a minute before running the code again. Then in onPause() or wherever you want you set the flag to false. If you need to update the UI then call publishProgress() inside your loop and put the UI code in onProgressUpdate()
You can remove the AsyncTask and just do the proccess with Runnable in this way you can make the repetitions that you need. If this does not work you can set a flag to stop the proccess like said codeMagic.
runable = new Runnable() {
public void run() {
try {
//Proccess
while (flag)
{
//Proccess
handler.postDelayed(this, 3000);
}
}catch(Exception e)
{
Log.i("Log","Error: "+e);
}
};
handler.postDelayed(runable, 3000);
#Override
public void onPause() {
super.onPause();
flag=false;
handler.removeCallbacks(runnable);
}
#Override
public void onResume() {
super.onResume();
flag=true;
handler.postDelayed(runable, 3000);
}
I hope this help.
How can I make this happend?
Thread t = new Thread(new Runnable() {
#Override
public void run() {
FacebookConnectTask task =
new FacebookConnectTask("facebookId", "token", "email", facebookGender,0, 0);
task.setOnPreExecuteListener(this);
task.setOnDoneListener(this);
task.execute();
}
});
t.start();
public void onPreExecute() {
progressbar.setVisibility(View.VISIBLE);
}
public void onDone() {
progressbar.setVisibility(View.GONE);
}
Since I am opening a new thread, I can not change a UI element in it, so, How can I manage to do something to the UI, when the task starts and when it's finished?
You could do the work in an AyncTask. The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.
preExecute() and postExecute() offer you access to GUI before and after the heavy lifting occurs in this new thread, you can even pass the result of the long operation to postExecute() to then show any results of processing.
More here: http://developer.android.com/reference/android/os/AsyncTask.html
Example here: http://www.vogella.com/articles/AndroidPerformance/article.html
inside your activity
private Handler myHandler=new Handler();
next in your on done callback
public void onDone() {
myHandler.post(new Runnable(){
#Override
public void run() {
progressbar.setVisibility(View.GONE)
}
})
}
But as already was said. AsyncTask is more siutable for it
I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!
There are several ways for doing that,
AsyncTask -
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.
You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}
Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3
You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}
Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};
The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.