I\'m new to Android and I\'m trying to use the UI-Thread, so I\'ve written a simple test activity. But I think I\'ve misunderstood something, because on clicking the button
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.success1);
new Thread(new Runnable() {
@Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//update ui on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
gifImageView.setGifImageResource(R.drawable.success);
}
});
}
}).start();
}
Just wrap it as a function, then call this function from your background thread.
public void debugMsg(String msg) {
final String str = msg;
runOnUiThread(new Runnable() {
@Override
public void run() {
mInfo.setText(str);
}
});
}
You can use from this sample :
In the following example, we are going to use this facility to publish the result from a synonym search that was processed by a background thread.
To accomplish the goal during the OnCreate activity callback, we will set up onClickListener to run searchTask on a created thread.
When the user clicks on the Search button, we will create a Runnable anonymous class that searches for the word typed in R.id.wordEt EditText and starts the thread to execute Runnable.
When the search completes, we will create an instance of Runnable SetSynonymResult to publish the result back on the synonym TextView over the UI thread.
This technique is sometime not the most convenient one, especially when we don't have access to an Activity instance; therefore, in the following chapters, we are going to discuss simpler and cleaner techniques to update the UI from a background computing task.
public class MainActivity extends AppCompatActivity {
class SetSynonymResult implements Runnable {
String synonym;
SetSynonymResult(String synonym) {
this.synonym = synonym;
}
public void run() {
Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
synonym, Thread.currentThread().getId()) + " !");
TextView tv = (TextView) findViewById(R.id.synonymTv);
tv.setText(this.synonym);
}
}
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button search = (Button) findViewById(R.id.searchBut);
final EditText word = (EditText) findViewById(R.id.wordEt);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Runnable searchTask = new Runnable() {
@Override
public void run() {
String result = searchSynomim(word.getText().toString());
Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
word.getText(), Thread.currentThread().getName()));
runOnUiThread(new SetSynonymResult(result));
}
};
Thread thread = new Thread(searchTask);
thread.start();
}
});
}
static int i = 0;
String searchSynomim(String word) {
return ++i % 2 == 0 ? "fake" : "mock";
}
}
Source :
asynchronous android programming Helder Vasconcelos
There are several techniques using of runOnUiThread(), lets see all
This is my main thread (UI thread) called AndroidBasicThreadActivity and I'm going to update it from a worker thread in various ways -
public class AndroidBasicThreadActivity extends AppCompatActivity
{
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_basic_thread);
textView = (TextView) findViewById(R.id.textview);
MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
Thread t1 = new Thread(myTask, "Bajrang");
t1.start();
}
}
1.) By passing Activity's instance as an argument on worker thread
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
activity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
2.) By using View's post(Runnable runnable) method in worker thread
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
AndroidBasicThreadActivity.textView.post(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
3.) By using Handler class from android.os package If we don't have the context (this/ getApplicationContext()) or Activity's instance (AndroidBasicThreadActivity.this) then we have to use Handler class as below -
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
If using in fragment then simply write
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// Do something on UiThread
}
});
Try this: getActivity().runOnUiThread(new Runnable...
It's because:
1) the implicit this in your call to runOnUiThread is referring to AsyncTask, not your fragment.
2) Fragment doesn't have runOnUiThread.
However, Activity does.
Note that Activity just executes the Runnable if you're already on the main thread, otherwise it uses a Handler. You can implement a Handler in your fragment if you don't want to worry about the context of this, it's actually very easy:
// A class instance
private Handler mHandler = new Handler(Looper.getMainLooper());
// anywhere else in your code
mHandler.post(<your runnable>);
// ^ this will always be run on the next run loop on the main thread.