From my generic fragment, I have this method:
protected void loadDataListWithDelay() {
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
loadDataList();
}
}, DELAY_START_LOADING);
}
This method allows to start a new loading data from server (with Volley networking).
In my loadDataList() method there are some views visibility setting:
protected void loadDataList(String url, ArrayList<BaseFilters> filters,
String query, boolean byPassSearchMode) {
...
mLoadingDataListView.setVisibility(View.INVISIBLE);
mListContainer.setVisibility(View.VISIBLE);
...
This code runs perfectly, but I have this crash this morning on mobile with Android 6.0.1.
Could you help me guys?
I will give you a good advice, if you want to do postDelayed, take a view in your fragment (or any view), and do postDelayed with it. i.e. textView.postDelayed(.. This way you can be sure you are on the ui thread.
Why not use runOnUiThread instead of creating a new handler ?
runOnUiThread(new Runnable() {
#Override
public void run() {
loadDataList();
}
});
If you need a delay, then you can use a handler inside the runOnUiThread
runOnUiThread(new Runnable() {
#Override
public void run() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
loadDataList();
}
}, DELAY);
}
});
Hi i know there are lot of answers to this topic. But I tried a lot and it doesn't work. I want to show a toast inside a thread of a service. How can i solve this problem. Using getApplicationContext() etc. doesn't work.
I start the Service from an Activity (no bounding).
public class CarDataService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
startThreadUpdatingDatabase();
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); //it works
}
private void startThreadUpdatingDatabase(){
Log.d("Database", "startThreadUpdatingDatabase(was called)");
new Thread(new Runnable() {
public void run(){
..
// here i want to use a toast!!!
}
}).start();
}
}
Thank you!
You have to start the thread:
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Your message",Toast.LENGTH_LONG).show();
}
}).start();
public Contect context;
member variable
onStartCommand(){
context = getApplicationContext)
}
acquivre reference to the context before you start the thread
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(context,"Your message",Toast.LENGTH_LONG).show();
}
}).start();
and there you go
use AsyncTask instead that helps in context management
http://www.androidsnippets.com/use-toast-wherever-you-want
Handler h = new Handler(context.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context,message,Toast.LENGTH_LONG).show();
}
});
see if this works out
Show your Toast using UI-Thread
new Thread(new Runnable() {
#Override
public void run() {
// SHOW TOAST
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
});
//... start DB work
}
}).start();
If you have no access to an activity, so do it this way:
new Thread(new Runnable() {
#Override
public void run() {
// no activity, so use Handler & mainlooper
new Handler(Looper.getMainLooper()).post(
new Runnable() {
public void run() {
// yourContext is Activity or Application context
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
}
);
//... start DB work
}
}).start();
Look at this: Static Way to get Context on android?
i created running app and i trying to create stopper that starting when user press start button.
but when i using thread the application return black screen
,this is my onCreate method i added thread
Thread t = new Thread() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
SetTextOnView();
}
});
}
};
t.start();
the SetTextOnView method contain
public void SetTextOnView()
{
TextView timedisp = (TextView) findViewById(R.id.stopperdisplay);
while(true)
{
timedisp.setText(String.valueOf(total));
}
}
the problem start when i add the while statment
why is that?
Do the loop in your thread to not block the ui thread + add some delay to not block the ui thread :
Thread t = new Thread() {
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
SetTextOnView();
}
});
Thread.sleep(1000);
}
}
};
And your SetTextOnView :
public void SetTextOnView()
{
TextView timedisp = (TextView) findViewById(R.id.stopperdisplay);
timedisp.setText(String.valueOf(total));
}
I have two processes "Loaddata(); Workoffline();", now I want the process Loaddata(); to run until it is completed, the application can switch to the next process Workoffline(); .But I do not know how to do, expect people to help me.
public void test(){
runOnUiThread(new Runnable() {
#Override
public synchronized void run() {
loaddata();
//your UI interaction code here
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
workoffline();
}
});
}
- The best approach will be to use CountDownLatch in java.util.concurrent package.
- You can use CountDownLatch's method countDown() to notify the completion of the loaddata(), and then use await() method to allow the execution of workoffline().
- Another way is to use join()
Eg:
Thread t1 = new Thread(new Runnable(){
public void run(){
handler.post(new Runnable(){ // Declare the Handler handler = new Handler();
// in onCreate()
public void run(){
loaddata();
}
});
}
});
t1.start();
try{
t1.join();
}catch(InterruptedException ex){
}
Thread t2 = new Thread(new Runnable(){
public void run(){
handler.post(new Runnable(){
public void run(){
workoffline();
}
});
}
});
t2.start();
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 - the app does not respond anymore
public class TestActivity extends Activity {
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread(){
runOnUiThread (new Thread(new Runnable() {
public void run() {
while(i++ < 1000){
btn.setText("#"+i);
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}));
}
}
Below is corrected Snippet of runThread Function.
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.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 have it back-to-front. Your button click results in a call to runOnUiThread(), but this isn't needed, since the click handler is already running on the UI thread. Then, your code in runOnUiThread() is launching a new background thread, where you try to do UI operations, which then fail.
Instead, just launch the background thread directly from your click handler. Then, wrap the calls to btn.setText() inside a call to runOnUiThread().
runOnUiThread(new Runnable() {
public void run() {
//Do something on UiThread
}
});
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
}
});
We use Worker Thread to make Apps smoother and avoid ANR's. We may need to update UI after the heavy process in worker Tread.
The UI can only be updated from UI Thread. In such cases, we use Handler or runOnUiThread both have a Runnable run method that executes in UI Thread.
The onClick method runs in UI thread so don't need to use runOnUiThread here.
Using Kotlin
While in Activity,
this.runOnUiThread {
// Do stuff
}
From Fragment,
activity?.runOnUiThread {
// Do stuff
}
Using Java,
this.runOnUiThread(new Runnable() {
void run() {
// Do stuff
}
});
For fragment use that:
requireActivity().runOnUiThread(() -> {
//your code logic
});
For activity use that:
runOnUiThread(() -> {
//your code logic
});
runOnUiThread is used in a way the UI can be updated with our background thread. For more: https://www.tutorialspoint.com/how-do-we-use-runonuithread-in-android
thy this:
#UiThread
public void logMsg(final String msg) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
}
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
This is how I use it:
runOnUiThread(new Runnable() {
#Override
public void run() {
//Do something on UiThread
}
});
#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();
}
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.