Application freezes when setting TextView text - java

I have to update a TextView from another class (not a activity) with the result from a method which can be slow to finish its search. While the method don't finish I thought set the TextView text to something like "loading..." and finally, after method result is ok, set the text to that result. Currently I'm doing something like this:
textView.setText("loading...");
Search s = searcher.search();
textView.setText(s.result);
Firstly, this still freezes the application until result is ok, once didn't not used new Threads. I know that to set content to Android widgets we have to do it inside the uiThread, but I don't know how to do it in my case, once I'm not inside a Activity.
In second place, that approach are not showing the "loading..." text. When I call that code the application just freezes and back with the final text.
Then, how to avoid that freeze/breaking until content is ok?

Do not do heavy operation inside MainThread (UI) in Android. For your case take a look to AsyncTask. It give you a method doInBackground where you should make some background stuff (http request, file i/o) then you will get call onPostExecute, that method will called on UI Thread with the results of doInBackground method. Another example.

I think the main thing to understand is that only UI specific tasks should run on the UI thread. If it is not UI related then it should run on another thread ideally as an AsyncTask.
Performing a search, generally speaking, is very performance heavy as you have pointed out. This will block the UI thread from updating the UI which will lead to unresponsive UIs and users may perceive this a crash or a slow app.
So firstly, to run the updating on the UI Thread.
runOnUiThread(() ->{textView.setText("loading...");});
then perform the search on a different thread
then once the search is finished update the UI using the same method as above

Related

i'm so confused about Threads

I read a lot about threads but don't understand yet :( let me explain to you what I have learned about threads. all we are working on such as codes any thing worked on UI thread or Main thread right? After that what happens if we call runOnUiThread? and my other question how do we know it's Time to use a new thread? I mean how do we understand we are working on another thread or replace or code in the new thread?
I know this is an unclear question but I don't understand as well. Please help me Thanks, john.
Let me try to answer. Actually Android has Main Thread (also called as UI Thread) and other thread.
Main Thread is basically for showing UI and other thread is for processing other big processes such as connecting to the server, etc.
runOnUiThread is called when you want to move from other thread to main thread. It is needed since only main thread can show/display result on UI. So when you have done some process on other thread, and you want to display the result on the apps, you need to show it on main thread by calling runOnUiThread.
We working on other thread only if it is a big or lengthy process like taking data from the server, load data, etc. And we move from other thread to main thread whenever we want to show some UI result.
Easiest way is to use AsyncTask<> class. You'll need to override three functions.
doInBackGround(...) : The codes that gets executed in background thread.
onPreExecute(..) : code that gets executed before background thread
completes executing like displaying progress bars, etc.
onPostExecute(...): Code that gets executed after background thread
has completed running. Perform task like updating UI in here
One general rule of thumb is: Don't use multithreading if you don't need to. Multithreading is always error-prone, and in many situations there's no benefit. Basically, you start a new thread whenever you execute a lengthy operation (i.e. some extensive computation like image processing) that would block the main thread for some time, so the application would become unresponsive.

Android Webview loadUrl does not work when coming from a worker thread

I am developing an app that contains a web view. A certain times during the app it does a call to Webview loadUrl.
Sometimes the call will come directly from an event on the UI thread and other times it comes from an event on a background worker thread. When it originates from the background thread I do a call to runOnUIThead() to ensure the actual call to loadURL happens on the UI thread.
What I am experiencing is that loadUrl() works fine when originating from the UI thread, however it fails to work when it comes from a worker thread (even though the actual call to loadUrl happens via a runnable I pass into runOnUIThread()).
Having set a break point I can see that in both instances loadUrl() is being called on the UI thread. Yet it works in one case but not the other.
I am currently sifting through the Android Webview source code to see if I can track down why sometimes it works and sometimes it doesn’t. If anyone can shed any light on the matter it would be greatly appreciated.
--- UPDATE ---
I have tried a few suggestions from this post here: WebView loadUrl works only once
Mainly doing the following before calling loadUrl:
webView.clearCache(true);
webView.loadUrl("Url");
And:
webView.clearCache(true);
webView.clearView();
webView.reload();
webView.loadUrl("about:blank");
webView.loadUrl("Url");
Unfortunately neither of them work.
In general, its not safe to create view outside of main thread.
In your particular case, this is not allowed, because WebView creates Handler() in its constructor for communication with UI thread. But since Handler's default constructor attaches itself to current thread, and current thread does not have Looper running, you're getting this exception.
You might think that creating a looper thread (that must be alive at least as long as WebView) might help you, but this actually a risky way to go. And I wouldn't recommend it.
You should stick with creating WebViews in main thread. All controls are usually optimized for fast construction, as they are almost always created in UI thread.
or You can call webview like this
runOnUiThread(new Runnable() {
#Override
public void run() {
// your webview method
}
});

Android/Java . AsyncTask /Thread passing data back to UI whenever I want it(not only in pre/postExecute)

I am struggling with the some threading stuff in android.
The situation is, that I have a table, which is getting filled during ui actions of the user.
And this table is added to a queue. I chose LinkedBlockingQueue until now.
(Please correct me if this is a bad Idea).
At the same time there is a background-thread, that should fetch (read) the queue and prepare another table, which itself then is passed to a method, which should be invoked on the UI thread.
(Meaning, the background-thread only collects the queued table in background in order to pass them to another method later on ).
So I read about the various approaches to do this in some ways and found myself in the AsyncTask.
But AsyncTask only allows me pre execution or post execution as options to invoke methods/code in the UI thread.
I want to decide myself, when I invoke some methods on the UI thread , because the background-thread still has to do some work after he invoked the method in UI thread.
Ah, as information: The background-thread never stops unless the user exits the application or a special idle timeout occurred.
And : Invoking the mentioned method on UI thread will also be parametrized.
But async task only allows me pre execution or post execution as options to invoke methods/code in the ui thread.
No. onProgressUpdate() also runs on the UI Thread. You run this function by calling publishProgress() in doInBackground() when the UI needs to be update while background operations are still running.
Here is an answer with an example of using it
publishProgress() Docs
Make sure to read through the AsyncTask Docs thoroughly several times. They are a bit tricky at first until you get it.

Continuously run a piece of code in Android

I'm making an Android game, and I'll need a continuously running thread for basically everything.
Now, however, I'm making the main menu (I always start simple, I'm new to coding), and I want an image to float across the main screen. I know how I could code that (determining the starting location, changing it), but I don't know how to run such a piece of code continuously (outside the UI thread).
P.S.: Please be easy on me. I know I'm probably missing something obvious, but I have virtually no Java experience at all.
1. Create a Non-UI thread, with Handler. And run it within Controlled loop using a boolean variable. Handler will be helpful in putting the output of the Non-Ui thread on the
Ui thread.
2. You can use an AsyncTask, introduced in android to synchronize the UI with Non-Ui thread.
while(check){//your code}
In run method you can put put a globle boolean variable to check the condition.

Android Thread in shouldOverrideUrlLoading

I had some code in a shouldOverrideUrlLoading, that downloads the data, converting if necessary, and shows in a WebView using loadData or loadUrl. I moved this to a thread (a class implementing Runnable), and now it doesn't lock up the UI while the next page is loading. Unfortunately, sometimes it locks up the whole app, and pausing while debugging shows it seems to be going nowhere (deadlock?)
I'm guessing this is because UI isn't thread-safe, not even webkit loadData/loadUrl? Is there a way to set some sort of onFinish action that runs in UI thread after download/convert has finished? Or would it be enough to store the current thread, and cancel it before running another thread??
adding a synchronized (WebView) { around the thread's code fixes this.

Categories