I need to start background task. Task call async http request and if condition is valid show alert.
I implemented it but I receive this error:
java.lang.RuntimeException:
Can't create handler inside thread that has not called
Looper.prepare()
This is my java code:
Timer timer = new Timer();
timer.schedule(new RequestScheduledTask(), intervalTask);
class RequestScheduledTask extends TimerTask {
#Override
public void run() {
myCall();
}
}
Can you help me please?
Thanks
Luca
for example I need refresh adapter list when data is changed. Data returned from webserver could to be changed or not. if it is changed I must refresh listview/adapter, else nothing.
myCall call server, get data response (using other framwork like volley) and then update list view.
When myCall start I want display loading indicator but when I show it, app crash with runtime exception
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
According to the following post you are doing something in a thread that is meant to be called on the main thread! What is myCall(); doing?
Can't create handler inside thread that has not called Looper.prepare()
And don't do http request with async tasks thats bad practice.
I would recomment to use volley:
http://www.itsalif.info/content/android-volley-tutorial-http-get-post-put
[edit]
Okay its the loading indicator that is should be called on the main thread. I guess you are doing it in the AsyncTask.
You can use Activity.runOnUiThread(Runnable()) to run a runnable to display it.
Related
I am new in Kotlin, I have a first activity with login, and second activity with recycle view. The data of recicle view is taken from http3 method.
Sorry for my bad english.
How I can show a dialogPopUp when I have code 404, and return in previous one login activity?
OkHttp callbacks are executed on a background thread if you use enqueue and showing a dialog is a UI task therefor it needs to be run on the UI thread.
In your case you can easily do this by running your dialog code using runOnUiThread.
runOnUiThread {
dialogPopUp("Error parameters", mContext ).showDialog()
}
Just as you have done in your else block.
You can also achieve this by using a Handler which has been created on the UI thread.
Update: Taking a closer look at your code I realized you're running fetchJson in a background thread by using the doAsync function. When you use enqueue on a OkHttp.Call you're basically sending it to be executed on a background thread so no need to use doAsync.
If you remove the doAsync you don't need to use runOnUiThread anymore as the callback will be executed on the UI thread.
Can't create handler inside thread that has not called Looper.prepare()
This basically means that you need to use the UI thread when calling this code. The UI thread will need to be used for showing your dialog.
You can do:
runOnUiThread {
dialogPopUp("Error parameters", mContext ).showDialog()
}
I have a layout with 2 tabs in it which are implemented via fragments i.e. each tab has its own fragment. They is a SwipeRefreshLayout in each of the layouts associated with the fragments.
Also there are two async tasks which make an http call to a script that returns JSON data.I implemented the first async task and it worked fine but however when I tried executing the second one the app keeps crashing. Log cat is not of much help but these were the most important lines I saw:
java.lang.RuntimeException: An error occured while executing doInBackground()
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
These errors occured when an http request was created. Any idea how I can get around this?
In a different thread from the UI thread you must create a Handle and send a runnable for the UI thread . follows the code
Handler handler = new Handler (Looper.getMainLooper());
handler.post (new Runnable () {
#Override
public void run () {
// ... Update view
}
});
A user is getting an error on their phone when executing the code below, I am checking to see if the user is currently on a call or not before I run an AsyncTask making a Web Service call. The reason I am doing this is because some people are losing internet connection when on a call so i check every 5 seconds to see if they are on a call or not. If they are not then AsyncTask gets called
do{
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run() {
onCall = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
.getCallState() != TelephonyManager.CALL_STATE_IDLE;
if(!onCall){
new CallRegWS().execute();
}
}
},5000);
}while(onCall);
I do not have the full stack trace only this showing me the error
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
obviously not too helpful but that is all I have to go on. they keep getting that error so it must be happening when I create the handler.
All this is done in the main thread so I dont know what the problem is, any insight on how I could fix this?
Update
this is called from a service and the method is in a separate class
Try Handler handler = new Handler(Looper.getMainLooper());
Also, see this post regarding this error: http://levinotik.com/loopers-handlers-runtimeexceptions-explained/
First of all you have to know that, Handlers automatically attach to the thread where are created as specified in the documentation:
Handler Class Overview
A Handler 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. 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. Handler | Android Developers
Now, taking that on count and since the current thread don't have a message queue, in order to work properly the thread needs an actual "Queue", and that's exactly what the system is telling you to do, by calling Looper.prepare() you are creating a Message Looper within the thread you created because by default Threads do not have a Message looper as mentioned in documentation:
Looper Class Overview
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped. Looper | Android Developers
In other words and in a simple manner, the Main UI DOES have a Message Queue already prepared, and that's why you don't see that error when calling new Handler() within "onCreate, onStart, onResume etc...", but for any worker thread created the system needs a queue to send the messages to when using handlers, although the code doesn't show it, i bet that code is being executed in a worker thread either normal Thread or doInBackground method of an AsyncTask and that's what causes the error, to avoid it remember to always call Looper.prepare before creating a handler from a worker thread.
Hope this Helps.
Regards!
How do you know this is running on the Main thread? And when and where is this getting called from? Instead of creating your handler right before you use it, create it in the onCreate method of your Activity or your Service (depending on what this is).Then in your onDestroy null the value out.
I am trying to use an AsyncTask class that I created to update a MapView. The problem is I am getting this error when I make my call to execute the AsyncTask:
"Can't create a Handler inside a thread that has not called Looper.prepare()"
I have tried running the Task on the UI Thread using
Handler hand = new Handler(Looper.getMainLooper());
hand.post(new Runnable() {
public void run() {
new RxThread().execute();
}
});
But that just gives me the same error. I realize that my MapView doesn't call looper prepare, and that I'm having troubles getting this to work since I'm running the MapView on a seperate activity rather than the Main Activity. Does anyone have a good solution to this?
IIRC, your error is because you are first referencing AsyncTask on a background thread. You can only create and execute() an AsyncTask on the main application thread.
I'm trying to start a an activity only after some data is ready in the Service
I'm trying this with a timer task which constantly polls the service for the data readness
public class SplashTask extends TimerTask {
#Override
public void run() {
Log.i(MY_DEBUG_TAG, "Internet is accessible, Running some Spalsh screen Tasks ");
if(mBoundService.isDataReady()) {
Log.e(MY_DEBUG_TAG, "Data is ready in service..");
startActivityForResult(new Intent(SplashDroid.this, FunWithDataActivity.class), 3);
} else {
Log.e(MY_DEBUG_TAG, "Data not ready in service..");
}
Log.i(MY_DEBUG_TAG, "Spalsh Tasks fnished..");
}
}
Issue is that when data is ready and FunWithDataActivity about to start, i'm getting the following error
07-27 14:53:40.614: ERROR/AndroidRuntime(1042): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
startActivityForResult has to be called from the UI thread (which is not the thread in which the handler executes). To achieve this, move the startActivityForResult code to a Runnable and run it using runOnUiThread inside the run().
You can't use startActivityForResult from non-UI thread. You can either use runOnUiThread() or Handler.post().
Also, you shouldn't really use separate thread for polling. Use Handler's postDelayed() function for polling. This way you won't wasted whole thread for simple polling. For an example see: Repeat a task with a time delay?
Try to use the CountDownTimer class instead. You can also see this answer for an example: TimerTask in Android?
Worth looking into these post:
Can't create handler inside thread that has not called Looper.prepare()
Can't create handler inside thread that has not called Looper.prepare() inside AsyncTask for ProgressDialog
If not resolved,Could u post your code where u r facing the problem!!