Here is my code:
public class MainActivity extends AppCompatActivity {
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runnable=new Runnable() {
#Override
public void run() {
Log.i("hello","runnable") ;
}
};
}
}
Why is it not printing log? Do I need a handler and then pass runnable object in it? Does run() method runs only once?
Currently you just define your runnable, but it will be never called. There are some ways how you can use a runnable e.g. in a thread or also in a Handler.
Here is an example for a Thread where you cannot update the UI:
new Thread(runnable).start();
If you need to update the UI you should use a Handler like this:
new Handler().post(runnable); // do as soon as possible
new Handler().postDelayed(runnable, 300); // do it after 300ms
Normally it doesn't make sense but you can use your runnable also as a kind of callback like this:
runnable.run();
A runnable can been used multiple times by using that three examples above multiple times.
Related
Can someone tell me why this doesn't work? I am trying to figure out how to use thread/runnable. Thread doesnt do much but just to loop and let the main thread know to update the text. I dont know what I missed, the centertext doesnt update. Thanks so much.
public class MainActivity extends AppCompatActivity {
TextView centerText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final SysTimeObj sysTimeObj = new SysTimeObj();
centerText = findViewById(R.id.centerText);
Handler stHandler = new Handler(getMainLooper()){
#Override
public void handleMessage(#NonNull Message msg) {
super.handleMessage(msg);
centerText.setText("thread updated");
}
};
startThread(sysTimeObj, stHandler);
}
public void startThread(SysTimeObj sysTimeObj, Handler handler){
clockThread rc = new clockThread(sysTimeObj, handler);
Thread t1 = new Thread(rc);
t1.start();
}
}
public class clockThread implements Runnable {
//private String sysTime;
private Handler handler;
SysTimeObj sysTimeObj;
public clockThread(SysTimeObj sysTimeObj, Handler mHandler){
//sysTime = GregorianCalendar.getInstance().getTime().toString();
this.sysTimeObj = sysTimeObj;
handler = mHandler;
}
#Override
public void run() {
sysTimeObj.setTime();
handler.postDelayed(this, 100);
}
}
You want to do something on the Main/UI Thread after a certain amount of time ? On Android, you don't need a new thread for that.
The Main Thread has a message queue that you can Post to. That message queue is emptied on a regular basis. Posted messages can be configured to be executed at a later time (which is what you seem to want).
To post messages, you need to create a Handler for the target thread. This Handler will let you send messages to that thread. Then, Post a Runnable to that thread using one of the posting methods availlable (here, postDelayed).
You'll end with something like this :
public class MainActivity extends AppCompatActivity {
private TextView yourTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourTextView = findViewById(R.id.yourTextView);
Handler handler = new Handler(getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
yourTextView.setText("Updated after 100 ms");
}
}, 100);
}
}
If threads is really what you want, I suggest you look at AsyncTasks. You might also want to look at the official documentation about Process and Threads on Android Developpers.
I am trying to call my takepicture() method after every 1 minute. So, I tried using the handler class and then tried calling my method within its run function. However, when I tried doing a step wise debugging, it never enters the run method at all. Can anyone please suggest me what I am doing wrong? I am trying to call it from my fragment.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
Log.d("HandlerThread","This is from the HandlerThread");
takePicture();
handler.postDelayed(this, 60000);
}
};
}
Try this:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Log.d("HandlerThread","This is from the HandlerThread");
takePicture();
}
}, 60000);
}
Rather than defining the handler.postDelayed within run method.I have just changed the call within your main thread itself.
Kindly mark it as answer if it solves your problem.
You never call any method that would run the Runnable. You only specified its behavior inside the run() function.
In order to start the Runnable, call something like handler.postDelayed(r, 0);
Just an info: please note that your Handler is still tied to the main Thread. See this answer and this one if you want to run it on a separate thread.
You should make an initial call to start the handler functionality.
ie , handler.post(r);
I'm trying to build an Android app which will repeatedly run some process every 10 mins.
As I found out Handlers are more reliable than timers or scheduling. So I'm going to develop my app using the Handlers using the given below codes.
I'm little bit concerned that the below codes will create separate Handlers at each time I start the app and keep them running parallel, may be since I'm creating the Handler on onCreate.
So what is the best way to keep only a single Handler runs in background at a time?
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler(); // new handler
handler.postDelayed(runnable, 1000*60*10); // 10 mins int.
setContentView(R.layout.activity_pro__sms);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
/* my set of codes for repeated work */
foobar();
handler.postDelayed(this, 1000*60*10); // reschedule the handler
}
};
You can extend Application class and do your work in it.
public class App extends Application {
private Handler handler;
#Override
protected void onCreate() {
super.onCreate();
handler = new Handler(); // new handler
handler.postDelayed(runnable, 1000*60*10); // 10 mins int.
setContentView(R.layout.activity_pro__sms);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
/* my set of codes for repeated work */
foobar();
handler.postDelayed(this, 1000*60*10); // reschedule the handler
}
};
}
And declare your class in manifest:
<application android:name=".App">
Edited
But it will work only if your app is running, otherwise you can use AlarmManager.
I decided to answer my own question since I've found out how to do it right way. The Android way. First of all what I was trying to do and posted in the question is a wrong approach to my requirement. Now I'm posting this so someone else will not do it wrong way but the following way.
Android has few options for timing.
Timer-task -> runs while application is alive. best for short term timing. Resource usage is higher.
Handler -> runs while application is alive. But not suitable to used as a scheduler. (this is what I've asked and it's not the correct way to do that). Handlers are the best way to do something repeatedly till the app is killed.
Alarm-manager -> The best way to schedule something to happen in future even if the app is killed. (this is what I should apply for my app).
This is what I figured out. Correct me if I'm wrong.
first define an utility class
public abstract class HandlerPeriodRunnable implements Runnable {
private Handler periodHandler;
private int msPeriod;
public HandlerPeriodRunnable(Handler periodHandler, int msPeriod) {
this.periodHandler = periodHandler;
this.msPeriod = msPeriod;
}
#Override
public void run() {
periodRun();
if (msPeriod > 0) {
periodHandler.postDelayed(this, msPeriod);
}
}
abstract public void periodRun();
}
then use it
final Handler mUIHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUIHandler.postDelayed(new HandlerPeriodRunnable(mUIHandler, 1000) {
#Override
public void periodRun() {
}
}, 2000);
}
I have an activity named BuildingActivity that extends ListActivity.
In the onCreate() method, i'm running 7 database queries in a background thread. In that background thread, I am building an ArrayList<String> object from the data returned from the queries.
Now, I want to return that ArrayList<String> object back to my BuildingActivity thread.
Here's part of the code that Im working on:
public class BuildingActivity extends ListActivity {
private ProgressBar mProgressBar;
public ArrayList<String> buildings;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_building);
new Thread(new Runnable() {
#Override
public void run() {
ArrayList<String> list;
DataSource dbSource = new DataSource(getApplicationContext());
dbSource.open();
list = dbSource.getBuildingsList();
dbSource.close();
//*** NOW HOW DO I PASS list BACK TO onCreate()?
//*** I WANT TO MAKE buildings = list.
}
}).start();
if(!buildings.isEmpty()) {
// do Something.
// If i do buildings = list in the background thread,
// This will always be executed because the background thread can take
// some time to return the data. How do i make sure this part of
// code is executed only after the data has been returned?
}
}
}
My objective after this is to create a list from this returned list of buildings. And on clicking a building, another activity shall open. How do I get about this problem?
Thanks!
How do i make sure this part of code is executed only after the data
has been returned?
Instead of using Thread for doing task in background use AsyncTask which provide doInBackground for performing operation in background and onPostExecute methods run on UI Thread after completing background task
here use this
public void myMethod(){
Thread background = new Thread(new Runnable(){
#Override
public void run(){
Looper.prepare();
//Do your data rerieval work here
Runnable r=new Runnable() {
#Override
public void run() {
//return your list from here
}
};
handler.post(r);
Looper.loop();
}
});
background.start();
}
So I wanted to implement Timer in my Anroid program and I found out the better way to do that is using Handler class.
First I decided to write the simplest program using Handler - the text is set after 1 second. I'm totall beginner in Android, so I went through some tutorials on web especially that one http://developer.android.com/resources/articles/timed-ui-updates.html , but still my application shows error ("application mTimer stopped").
So could anyone point out where exactly am I making mistake? I would be gratefull, here's the code:
public class mTimer extends Activity {
TextView tv;
Button button1,button2;
Handler mHandler;
private Runnable myTask = new Runnable() {
public void run() {
tv.setText("text");
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1=(Button)findViewById(R.id.button1);
tv=(TextView)findViewById(R.id.textView1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mHandler.postDelayed(myTask, 100);
}
});
}
}
You should initialize your Handler in your onCreate method with at least a code like mHandler = new Handler();.
Note, that the myTask task will be run on the UI thread, since your handler is declared there
API Docs for Handler.postDelayed:
The runnable will be run on the thread
to which this handler is attached.