A WebView in a thread can't be created - android

i have some threads in which i create some views and prepare them to be displayed. Among them i also have a WebView. This code is executed in thread:
WebView lGraphWebView = null;
try{
lGraphWebView = new WebView(AppController.getAppController());
}catch (Exception e) {
Log.d("info", "error: " +e );
}
and it throws the following exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
This is a bit strange, because when i create a simple button all is OK. So, can anyone explane to me why on creation of a WebView i get this exception and if Looper.prepare() can help here?
Thanks in advance!

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.

You should not create or manipulate views in threads other than the main UI thread. For instance, you can use the Handler to post to the UI thread:
private Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
lGraphWebView = new WebView(AppController.getAppController());
}
});

Related

Understanding what Looper is about in Android

I had to add Looper to the following code:
public class MyRunnable implements Runnable
{
#Override
public void run()
{
Looper.prepare();
final Looper looper = Looper.myLooper();
new Handler().postDelayed(
new Runnable()
{
#Override
public void run()
{
try
{
}
catch (Exception ex)
{
}
finally
{
looper.quit();
}
}
}, 100);
Looper.loop();
}
}
Notice that I have a runnable inside a runnable. The nested runnable gets executed through a Handler. Initially I didn't have Looper but Android complained that I needed to call Looper.prepare before executing another thread.
I read up on Looper but it still seems kind of cryptic. It seems to act like some kind of internal messaging pipeline. It isn't clear to me why this is necessary since there are no messages going from my outer runnable to my inner runnable. Even though that is true, it seems that Android just makes the hard rule that if you call a thread from a thread, you MUST also call Looper.prepare. Even if I accept that as-is, it still doesn't help to understand why I need to call looper.loop and looper.quit. If I omit Looper.loop, my Handler never runs and that is what isn't clear. What does Looper.loop do that allows my Handler to run?
Here is a great article about that.
Looper and Handler in Android
It comes along with a simple schema that leads to straight understanding of relationship between Loopers and Handler.
On this schema, we see that, within the same thread (depicted by the big rectangle), no matter how many handler you create, they will all be using the same Looper, i.e., the unique looper of this thread.
Note:
Looper have to be prepared to allow associated handler to process posted messages.
Android application, more precisely, android app UI thread(the main thread), already comes with a prepared looper (the mainLooper).
Here is how to Communicating with the UI Thread.
A simple concept of the looper:
Every worker thread you create and run ends once it performs its last operation.
To prevent your thread termination you can start a loop by calling Looper.loop(), think of it as while(true){} statement. Before calling Looper.loop() you have to prepare the loop with Looper.prepare(), if it is not prepared yet.
To terminate the loop and end your thread you will need to call looper.quit() on the looper.
Now for the notification you got from Android:
When you create a Handler in a thread, it will be bound to the thread it is created in and when you post runnable using this Handler, the code runs on the thread of the Handler.
So when the system saw that you want to run some code (especially 100ms in future) on a Handler that is bound to a thread that is going to die as soon as it finishes calling the post method it proposed to use Looper.loop() to prevent this thread from terminating and thus enabling you properly run the second Runnable in a still existing thread.
I find the following tutorial very helpful in understanding the concept of looper .
Intro to looper and handler

Threads And Handlers

My question Is that What is the difference between Thread and Handler
Q1) What are their effects When they are used in 1) Activity 2) Service
Q2) What is difference between them in context with their life span
I am using following codes for them.
1) ---------------------------
final Handler handler = new Handler();
Runnable runnable = new Runnable()
{
public void run()
{
// do somthing
handler.postDelayed(this, 1000);
}
};
runnable.run();
2) ---------------------------
handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
}
};
new Thread(new Runnable()
{
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {}
}
}
}).start();
Handler:
handler is used to do looper thing.that is to perform same task number of time.
handler can be executed on main thread.
about Handler if its used in service it may get stop if phone state change to sleep.
u can update the UI through handler if it used in activity.
Thread:
Thread is used to things on separate than the main thread of an activity.
thread always runs in background even if phone state changes to sleep mode.
u cant update the UI of as its not running on main thread.it can be done using asynctask not using simple java thread.
Q0) What is the difference between a thread and a handler?
A Thread is the same as it always is in programming. Each thread executes a single call to a method and then terminates. Each thread runs in parallel with every other thread. Threads are in short the way you have more than one thing happening at once.
Passing information between threads is notoriously difficult...
A Handler is Android's way of passing a message from one thread to another. Specifically it allows you to pass a set of instructions as a Runnable into a thread for that thread to execute. Typically they are used as a way for a thread to report its result back to the main thread when it's complete.
Q1) What are their effects When they are used in 1) Activity 2) Service
There is no difference between the way these two items behave in a service or an activity in general except that a service can exist in its own process if android is instructed to do so. Threads in different processes can not directly talk to one another. Services are there to share data,functionality and in some cases threads between activities. There is no requirement for them to have their own thread.
The one major point to note is that only the main thread can update the UI (activity).
Also networking specifically can not be done on the main thread. Networking is usually done from within a service so that the results can be shared but this is not necessary.
The limitations around what must and must not be done in the main thread make threading a little tricky, but these limitations are there to help you avoid freezing the UI unexpectedly.
Q2) What is difference between them in context with their life span I am using following codes for them.
Difficult to answer as I don't understand the purpose of your code.
As an example. Android no longer allows you to do any networking on the main thread as this could freeze the UI while it's waiting for the server to respond over a poor wifi connection. To change something on the UI based on something retrieved from the network you must use a thread to do the networking and pass the data back to the main thread to update the UI.
A (doctored) snippet from my code looks like this:
private final Handler handler = new Handler();
#Override
protected void onCreate( Bundle savedInstanceState ) {
// irreverent to the example
super.onCreate(savedInstanceState);
super.setContentView(R.layout.abstract_main_view);
// Here's the example
Thread networkThread = new Thread() {
#Override
public void run() {
// This could take several seconds
final Collection<Player> players = service.lookupAllPlayers();
Runnable uiUpdate = new Runnable() {
#Override
public void run() {
// This is quick, just adding some text on the screen
showPlayers(players);
}
};
handler.post(uiUpdate);
}
};
networkThread.start();
}
In this example:
The handler is created and exists for the duration of this activity. Because this class is constructed by the main thread, the Handler is also. This means that all messages posted to this handler will be executed by main.
networkThread is created and started by the main thread in onCreate. This lives until it has retrieved the data from the network and posted a response back to the main thread. Then it's done.
The Runnable uiUpdate is created by networkThread once all data is retrieved. It does not have a thread associated and so does not execute right away. Instead it is posted back to main using the handler. It is then executed on the main thread and discarded once complete.
One can use a Handler to inform one thread of events from another thread.
Typical usage would be to inform the UI Thread from other threads.
We can not modify UI elements from other threads directly. So we can define a Handler as a member of an Activity instead.
Activities are created on the UI Thread so this handler also is on UI Thread.
So then from another thread we send a message to the Handler. And on receiving the message the Handler modifies some UI elements.

Handler Does Not Execute Run

This feels like it should be a very simple task but I am having a lot of problems with it. In my program I have extended the WebView class for my own and am trying to add it to a layout programatically. Here is my code:
Looper.prepare();
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
MyWebView webView = new MyWebView(context,1,2,3,4);
appState.projectWebView.add(webView);
addView(webView);
}
});
When I run this code it does not execute. I have no idea why. Thanks for you time.
You cannot create a Handler outside of an UI thread. Well, you can, but you will have to turn that thread into a message queue with much more than just Looper.prepare().
What you need to do is pass an Activity to the class that contains the code in your sample, and call runOnUiThread() on it. Alternatively, you can pass a Handler created on a UI thread, for instance create it at the thread that runs your Activity UI, and then call post on that handler.
Note that this is awful advice, you seem to be trying to do things against the Android framework. But, without further information of what you are actually trying to do, there is no much that can be said.

What is the relationship between Looper, Handler and MessageQueue in Android?

I have checked the official Android documentation/guide for Looper, Handler and MessageQueue . But I couldn't get it. I am new to android, and got very confused with these concepts.
A Looper is a message handling loop: it reads and processes items from a MessageQueue. The Looper class is usually used in conjunction with a HandlerThread (a subclass of Thread).
A Handler is a utility class that facilitates interacting with a Looper—mainly by posting messages and Runnable objects to the thread's MessageQueue. When a Handler is created, it is bound to a specific Looper (and associated thread and message queue).
In typical usage, you create and start a HandlerThread, then create a Handler object (or objects) by which other threads can interact with the HandlerThread instance. The Handler must be created while running on the HandlerThread, although once created there is no restriction on what threads can use the Handler's scheduling methods (post(Runnable), etc.)
The main thread (a.k.a. UI thread) in an Android application is set up as a handler thread before your application instance is created.
Aside from the class docs, there's a nice discussion of all of this here.
P.S. All the classes mentioned above are in the package android.os.
It's widely known that it's illegal to update UI components directly from threads other than main thread in android. This android document (Handling Expensive Operations in the UI Thread) suggests the steps to follow if we need to start a separate thread to do some expensive work and update UI after it's done. The idea is to create a Handler object associated with main thread, and post a Runnable to it at appropriate time. This Runnable will be invoked on the main thread. This mechanism is implemented with Looper and Handler classes.
The Looper class maintains a MessageQueue, which contains a list messages. An important character of Looper is that it's associated with the thread within which the Looper is created. This association is kept forever and can't be broken nor changed. Also note that a thread can't be associated with more than one Looper. In order to guarantee this association, Looper is stored in thread-local storage, and it can't be created via its constructor directly. The only way to create it is to call prepare static method on Looper. prepare method first examines ThreadLocal of current thread to make sure that there isn't already a Looper associated with the thread. After the examination, a new Looper is created and saved in ThreadLocal. Having prepared the Looper, we can call loop method on it to check for new messages and have Handler to deal with them.
As the name indicates, the Handler class is mainly responsible for handling (adding, removing, dispatching) messages of current thread's MessageQueue. A Handler instance is also bound to a thread. The binding between Handler and Thread is achieved via Looper and MessageQueue. A Handler is always bound to a Looper, and subsequently bound to the thread associated with the Looper. Unlike Looper, multiple Handler instances can be bound to the same thread. Whenever we call post or any methods alike on the Handler, a new message is added to the associated MessageQueue. The target field of the message is set to current Handler instance. When the Looper received this message, it invokes dispatchMessage on message's target field, so that the message routes back to to the Handler instance to be handled, but on the correct thread.
The relationships between Looper, Handler and MessageQueue is shown below:
Let's start with the Looper. You can understand the relationship between Looper, Handler and MessageQueue more easily when you understand what Looper is. Also you can better understand what Looper is in the context of GUI framework. Looper is made to do 2 things.
1) Looper transforms a normal thread, which terminates when its run() method returns, into something that runs continuously until Android app is running, which is needed in GUI framework (Technically, it still terminates when run() method returns. But let me clarify what I mean, below).
2) Looper provides a queue where jobs to be done are enqueued, which is also needed in GUI framework.
As you may know, when an application is launched, the system creates a thread of execution for the application, called “main”, and Android applications normally run entirely on a single thread by default the “main thread”. But main thread is not some secret, special thread. It's just a normal thread that you can also create with new Thread() code, which means it terminates when its run() method returns! Think of below example.
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Now, let's apply this simple principle to Android app. What would happen if an Android app is run on a normal thread? A thread called "main" or "UI" or whatever starts application, and draws all UI. So, the first screen is displayed to users. So what now? The main thread terminates? No, it shouldn’t. It should wait until users do something, right? But how can we achieve this behavior? Well, we can try with Object.wait() or Thread.sleep(). For example, main thread finishes its initial job to display first screen, and sleeps. It awakes, which means interrupted, when a new job to do is fetched. So far so good, but at this moment we need a queue-like data structure to hold multiple jobs. Think about a case when a user touches screen serially, and a task takes longer time to finish. So, we need to have a data structure to hold jobs to be done in first-in-first-out manner. Also, you may imagine, implementing ever-running-and-process-job-when-arrived thread using interrupt is not easy, and leads to complex and often unmaintainable code. We'd rather create a new mechanism for such purpose, and that is what Looper is all about. The official document of Looper class says, "Threads by default do not have a message loop associated with them", and Looper is a class "used to run a message loop for a thread". Now you can understand what it means.
Let's move to Handler and MessageQueue. First, MessageQueue is the queue that I mentioned above. It resides inside a Looper, and that's it. You can check it with Looper class's source code. Looper class has a member variable of MessageQueue.
Then, what is Handler? If there is a queue, then there should be a method that should enable us to enqueue a new task to the queue, right? That is what Handler does. We can enqueue a new task into a queue(MessageQueue) using various post(Runnable r) methods. That's it. This is all about Looper, Handler, and MessageQueue.
My last word is, so basically Looper is a class that is made to address a problem that occurs in GUI framework. But this kind of needs also can happen in other situations as well. Actually it is a pretty famous pattern for multi threads application, and you can learn more about it in "Concurrent Programming in Java" by Doug Lea(Especially, chapter 4.1.4 "Worker Threads" would be helpful). Also, you can imagine this kind of mechanism is not unique in Android framework, but all GUI frameworks may need somewhat similar to this. You can find almost same mechanism in Java Swing framework.
MessageQueue: It is a low-level class holding the list of messages to be dispatched by a Looper. Messages are not added directly to a MessageQueue, but rather through Handler objects associated with the Looper.[3]
Looper: It loops over a MessageQueue which contains the messages to be dispatched. The actual task of managing the queue is done by the Handler which is responsible for handling (adding, removing, dispatching) messages in the message queue.[2]
Handler: It allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.[4]
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
Kindly, go through the below image[2] for better understanding.
Extending the answer, by #K_Anas, with an example,
As it stated
It's widely known that it's illegal to update UI components directly from threads other than main thread in android.
for instance if you try to update the UI using Thread.
int count = 0;
new Thread(new Runnable(){
#Override
public void run() {
try {
while(true) {
sleep(1000);
count++;
textView.setText(String.valueOf(count));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
).start();
your app will crash with exception.
android.view.ViewRoot$CalledFromWrongThreadException: Only the
original thread that created a view hierarchy can touch its views.
in other words you need to use Handler which keeps reference to the MainLooper i.e. Main Thread or UI Thread and pass task as Runnable.
Handler handler = new Handler(getApplicationContext().getMainLooper);
int count = 0;
new Thread(new Runnable(){
#Override
public void run() {
try {
while(true) {
sleep(1000);
count++;
handler.post(new Runnable() {
#Override
public void run() {
textView.setText(String.valueOf(count));
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
).start() ;

Handler or runOnUiThread solution for "Can't create handler inside thread that has not called Looper.prepare() "

Recently, I show up a toast in user thread and got the above runtime error.
From Can't create handler inside thread that has not called Looper.prepare(), they proposed use Handler as solution. However, I saw the solution is quite lengthy and cumbersome.
My own solution is to use runOnUiThread
private void showTooDarkToastMessage()
{
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
Toast toast = Toast.makeText(getContext(), getResources().getString(R.string.toast_toodark), Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
});
}
I was wondering, is there any shortcoming of using runOnUiThread, compared to Handler?
Because you are showing a UI element (a Toast message) runOnUiThread is perfect.
A Handler will run its task on the specified thread. For instance,
protected void onCreate( Bundle savedInstanceState )
{
Handler hander = new Handler();
//Create thread, post to handler
}
would create a new Handler that would run its posts on the UI thread. calling Activiy.runOnUiThread just posts the runnable specifically to the UI thread. By default, Handlers will run on whatever thread they were created in. The above code would work identical to using runOnUiThread because the onCreate method is run on the UI thread!
Handlers would be preferred if you needed to communicate between multiple background threads.
Because mobile devices have limited resources, work run on the UI thread should be kept relatively light. Intense work done on the UI thread can cause Application Not Responding (ANR) errors and can cause the OS to kill your process.
Actually runOnUiThread() using Handler inside. So, there is no downsides to use runOnUiThread() if you want to simple post some job to do in the UI Thread.
If you are interesting in difference between Handler and runOnUiThread() you can read about it in this answer

Categories

Resources