Multi threading in Android apps is a fundamental aspect, especially for larger apps. This is because it's not the best idea to have your whole app running on the main UI thread as it can become overloaded and become slow. Plus, unlike helper threads, stopping the main UI thread will cause the app to crash. For these reasons I have felt that it was important to address this. Now for most scenarios, using an Async task should do the job just nicely. However, these are really only designed for short tasks.
I wanted to gather a greater knowledge of opening new threads in my apps, so I decided to explore some possibilities and make a small app that would use a few different ways to open a new thread. There is also the very annoying fact that you cannot update the UI from a helper thread so I had to find a way to communicate with my main UI thread. You can do this by using a handy class in the Android API called 'Handler'. A Handler object allows you to send messages to it from another thread using the 'Message' class. You will need to make sure that the thread has access to the Handler object by passing it in the constructor etc.
The app I made opened up a thread in three different ways. The first way (t1 in the app screenshot) was via a class I made that implemented 'Runnable'. This is a pretty standard way in Java programming and is not special to Android (nor are any of the other methods apart from the handler... that is part of the API). This way allows you to define other characteristics and methods for that object alone and have each instance of the object and its behaviours run in a separate thread. The second way (t2 in the app screenshot) is done by making a new Thread object locally in the activity class as part of a method. This way allows you to code different behaviours that an object may have that all need to run in a separate thread. The last way of threading (t3 in the app screenshot) I decided to use a 'TimerTask'. In my code I made a nested class that extended the 'TimerTask' class. This class then had to implement a run function just like if you implemented 'Runnable'. The only difference is that when you come to run the thread you need to make a 'Timer' object and pass an instance of the 'TimerTask' you just made following with some more scheduling information. You can make this kind of thread execute an infinite amount of times or for a number of times. You can also set the frequency at which the thread re-executes. These types of threads would be good for a game loop, or some other type of task that needs to be scheduled and repeated.
The code is as follows:
public class MainActivity extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) this.findViewById(R.id.text_view1);
//Thread from another class (talking to this class)
Task1 t1 = new Task1(handler);
new Thread(t1).start();
//Thread from within a method
//pretty much the same behaviour as the previous but coded in a different manner
Task2();
//From a Timer thread
Timer timer = new Timer();
Task3 t3 = new Task3();
timer.schedule(t3, 0, 3000);
}
private void Task2 (){
new Thread (new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
String num = "t2";
//send a message
Message message = Message.obtain();
message.obj = num;
handler.sendMessage(message);
try {
//Notice how I am able to stop the thread
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message message){
//this is were the messages get sent to
tv.setText(tv.getText() + "\n" + message.obj.toString());
}
};
private class Task3 extends TimerTask {
@Override
public void run() {
String num = "t3";
//send a message
Message message = Message.obtain();
message.obj = num;
handler.sendMessage(message);
}
}
}
public class Task1 implements Runnable{
private Handler messageHandler;
public Task1 (Handler handler) {
this.messageHandler = handler;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
String num = "t1";
//send a message
Message message = Message.obtain();
message.obj = num;
messageHandler.sendMessage(message);
try {
//Notice how I am able to stop the thread
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) this.findViewById(R.id.text_view1);
//Thread from another class (talking to this class)
Task1 t1 = new Task1(handler);
new Thread(t1).start();
//Thread from within a method
//pretty much the same behaviour as the previous but coded in a different manner
Task2();
//From a Timer thread
Timer timer = new Timer();
Task3 t3 = new Task3();
timer.schedule(t3, 0, 3000);
}
private void Task2 (){
new Thread (new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
String num = "t2";
//send a message
Message message = Message.obtain();
message.obj = num;
handler.sendMessage(message);
try {
//Notice how I am able to stop the thread
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message message){
//this is were the messages get sent to
tv.setText(tv.getText() + "\n" + message.obj.toString());
}
};
private class Task3 extends TimerTask {
@Override
public void run() {
String num = "t3";
//send a message
Message message = Message.obtain();
message.obj = num;
handler.sendMessage(message);
}
}
}
public class Task1 implements Runnable{
private Handler messageHandler;
public Task1 (Handler handler) {
this.messageHandler = handler;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
String num = "t1";
//send a message
Message message = Message.obtain();
message.obj = num;
messageHandler.sendMessage(message);
try {
//Notice how I am able to stop the thread
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
No comments:
Post a Comment