问题
I am trying to use the AsyncTask class on android but I have a problem.
Here is my code:
public void CheckIfUserIsLogedIn ()
{
int userPresence = localDatabase.CheckUserPresence();
if (userPresence == 0)
{
setContentView(R.layout.main);
new checkCountryAsync().execute();
}
else
{
setContentView(R.layout.userlogedon);
}
}
class checkCountryAsync extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... aurl) {
int countryPresence = localDatabase.CheckCountryPresence();
if (countryPresence == 0)
{
CountryTable country = new CountryTable() ;
country.EnterCountry();
}
return null;
}
}
I don't know where I am doing something wrong. The method CheckCountryPresence() from the LocalDatabase class is only making a query and returns a result.
Thank you.
Edit: Here is the logCat:
02-20 08:41:25.804: W/dalvikvm(26458): threadid=10: thread exiting with uncaught exception (group=0x4001d5a0)
02-20 08:41:25.834: E/AndroidRuntime(26458): FATAL EXCEPTION: AsyncTask #1
02-20 08:41:25.834: E/AndroidRuntime(26458): java.lang.RuntimeException: An error occured while executing doInBackground()
02-20 08:41:25.834: E/AndroidRuntime(26458): at android.os.AsyncTask$3.done(AsyncTask.java:200)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.lang.Thread.run(Thread.java:1027)
02-20 08:41:25.834: E/AndroidRuntime(26458): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-20 08:41:25.834: E/AndroidRuntime(26458): at android.os.Handler.<init>(Handler.java:121)
02-20 08:41:25.834: E/AndroidRuntime(26458): at android.app.Activity.<init>(Activity.java:717)
02-20 08:41:25.834: E/AndroidRuntime(26458): at milos.mdpi.CountryTable.<init>(CountryTable.java:5)
02-20 08:41:25.834: E/AndroidRuntime(26458): at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:367)
02-20 08:41:25.834: E/AndroidRuntime(26458): at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:1)
02-20 08:41:25.834: E/AndroidRuntime(26458): at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-20 08:41:25.834: E/AndroidRuntime(26458): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
02-20 08:41:25.834: E/AndroidRuntime(26458): ... 4 more
回答1:
Seems you are doing some stuff to Update
your UI from a Non-UI
thread. So, you should put your stuff to update the UI inside runOnUiThread()
so that it executes the stuff on your UI hread itself.
UPDATE:
Just try to put your stuff for getting CheckCountryPresence();
inside onPreExecute()
. So your edited class should be like,
class checkCountryAsync extends AsyncTask<String, String, String> {
int countryPresence = 0;
@Override
protected void onPreExecute() {
countryPresence = localDatabase.CheckCountryPresence();
}
@Override
protected String doInBackground(String... aurl) {
Activity_name.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (countryPresence == 0)
{
CountryTable country = new CountryTable() ;
country.EnterCountry();
}
}
});
return null;
}
}
回答2:
Has your CountryTable class any interaction with the UI activity/class? Even fetching new rows for your adapter object? If yes, you cannot update your activity from outside the activity itself.
Fortunately you can overcome this pretty easily once you figure out the solution ;)
step 1:
Define an interface, like CheckCountryCallback
with a single method called onCheckCountryFinished(String taskResult)
;
Step 2: let the activity which call your asynctask implement this interface and its method.
Step 3: define a constructor for your asyncTask with a single parameter of type CheckCountryCallback
Step 4: override onPostExecute of your AT, and simply write mCaller.onCheckCountryFinished(result).
This is not enough sadly because you'd still be updating the ui from another thread but we're getting close!
In your implemented onCheckCountryFinished you should redirect the call to a handler you've to define in your activity. Send a message to that handler and you can update the UI (or the adapter or whatnot) from the handle message method of the handler.
Handler example:
private static final int UPDATE = 2;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == UPDATE) {
//do something with m.obj
myAdapter.notifyDataSetChanged();
}
}
};
callback example
public void onCheckCountryFinished(String result){
Message m = Message.obtain();
m.what = UPDATE;
m.obj = result;
handler.sendMessage(m);
}
回答3:
You are not passing your AsyncTask anything so make the parameters of AsyncTask all Void like this AsyncTask<Void, Void, Void>
then change doInBackground
to this protected Void doInBackground(Void... voids)
. Also, get rid of the onPreExecute
method since you are not even using it.
Also, it is unclear with you code provided, but CheckIfUserIsLogedIn
needs to be called from the UI thread. AsyncTask is really only meant to be run off of the UI thread.
回答4:
one of the problem that i faced, simpleCursorAdapter
also returns same error of looper
when called from thread
. So to remove that error, inside thread
ActivityName.this.runOnUiThread(new Runnable() {
public void run() {
String[] FROM = {/*your data here*/};
int[] TO = { /*your data here*/ };
adapter = new SimpleCursorAdapter(ActivityName.this, R.layout.row, cursor, FROM, TO);
listTimeline.setAdapter(adapter); //your own code here.
}
});
来源:https://stackoverflow.com/questions/9357513/cant-create-handler-inside-thread-that-has-not-called-looper-prepare-with-asy