android 版本 < 4 的异步任务问题
Asynctask issue on android version < 4
我开发了一个支持 android os 4 及更高版本的应用程序。我在应用程序启动期间使用 Asynctask 进行 Web 服务调用。
后来我将 minSdkVersion 更改为 9。以支持 android 2.3 及更高版本。但是相同的代码会抛出以下错误。
从 SplashActivity 线程调用 AsyncTask
mSplashTread = new Thread() { @Override public void run() {
try {
int waited = 0;
while (mActive && (waited < mSplashTime)) {
sleep(100);
if (mActive) {
waited += 100;
}
}
} catch (InterruptedException e) {
AppUtil.getInstance().logErrorMessage(TAG, e.getMessage());
} finally {
if (mIsBackPressed) {
finish();
} else {
GetMobilePremissionWebservice getMobilePermissionWebservice = new GetMobilePremissionWebservice(
mContext, SplashActivity.this);
getMobilePermissionWebservice.getMobilePermissionInfo();
}
} } };
日志:
Caused by: java.lang.RuntimeException: Can't create handler inside
thread that has not called Looper.prepare() at
android.os.Handler.(Handler.java:121) at
android.os.AsyncTask$InternalHandler.(AsyncTask.java:421) at
android.os.AsyncTask$InternalHandler.(AsyncTask.java:421)
我在网上查过了。有人说 Asynctask 内部使用 Handler。当它试图从 doInBackgrond() 访问 UI 时。
但相同的代码在 os 4 及更高版本中运行良好。我不知道 Android 版本 2.3 上的 Asynctask 有什么问题。
请帮我解决这个问题。
尝试在执行后更新 UI 而不是 doInBackground。
仅在 doInBackground 中获取数据,然后在执行后使用该数据来更新 UI.
也就是说你必须在主线程上调用AsyncTask.execute(...)
方法。
虽然前一句话在技术上不正确,但 99% 的时间都是预期的行为。毕竟您使用异步任务将计算从主线程卸载到后台线程。如果您已经在后台线程中,则不需要异步任务,对吗?
因为进行服务调用的正确格式如下。尝试按照以下格式进行网络服务调用
private class AsyncCallWS extends AsyncTask<Void, Void, Void>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
//show progress dialog
}
@Override
protected Void doInBackground(Void... params)
{
try
{
postData();
}
catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
//dismiss progress dialog
}
}
public void postData()
{
Thread t = new Thread()
{
public void run()
{
Looper.prepare();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://yourURL");
try
{
// Your webservice code......
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Looper.loop(); //Loop in the message queue
}
};
t.start();
}
}
这将解决您的错误...
实际上问题是我从线程调用 Asynctask。
通过使用 runOnUiThread,我从线程调用 Asynctask 解决了我的问题。
mSplashTread = new Thread() {
@Override
public void run() {
try {
int waited = 0;
while (mActive && (waited < mSplashTime)) {
sleep(100);
if (mActive) {
waited += 100;
}
}
} catch (InterruptedException e) {
AppUtil.getInstance().logErrorMessage(TAG, e.getMessage());
} finally {
if (mIsBackPressed) {
finish();
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
GetMobilePremissionWebservice getMobilePermissionWebservice = new GetMobilePremissionWebservice(
mContext, SplashActivity.this);
getMobilePermissionWebservice
.getMobilePermissionInfo();
}
});
}
}
}
};
但我仍然不知道为什么相同的代码在 android 版本 4.2 Samsung s3 中工作。
我开发了一个支持 android os 4 及更高版本的应用程序。我在应用程序启动期间使用 Asynctask 进行 Web 服务调用。
后来我将 minSdkVersion 更改为 9。以支持 android 2.3 及更高版本。但是相同的代码会抛出以下错误。
从 SplashActivity 线程调用 AsyncTask
mSplashTread = new Thread() { @Override public void run() { try { int waited = 0; while (mActive && (waited < mSplashTime)) { sleep(100); if (mActive) { waited += 100; } } } catch (InterruptedException e) { AppUtil.getInstance().logErrorMessage(TAG, e.getMessage()); } finally { if (mIsBackPressed) { finish(); } else { GetMobilePremissionWebservice getMobilePermissionWebservice = new GetMobilePremissionWebservice( mContext, SplashActivity.this); getMobilePermissionWebservice.getMobilePermissionInfo(); } } } };
日志:
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.(Handler.java:121) at android.os.AsyncTask$InternalHandler.(AsyncTask.java:421) at android.os.AsyncTask$InternalHandler.(AsyncTask.java:421)
我在网上查过了。有人说 Asynctask 内部使用 Handler。当它试图从 doInBackgrond() 访问 UI 时。 但相同的代码在 os 4 及更高版本中运行良好。我不知道 Android 版本 2.3 上的 Asynctask 有什么问题。
请帮我解决这个问题。
尝试在执行后更新 UI 而不是 doInBackground。 仅在 doInBackground 中获取数据,然后在执行后使用该数据来更新 UI.
也就是说你必须在主线程上调用AsyncTask.execute(...)
方法。
虽然前一句话在技术上不正确,但 99% 的时间都是预期的行为。毕竟您使用异步任务将计算从主线程卸载到后台线程。如果您已经在后台线程中,则不需要异步任务,对吗?
因为进行服务调用的正确格式如下。尝试按照以下格式进行网络服务调用
private class AsyncCallWS extends AsyncTask<Void, Void, Void>
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
//show progress dialog
}
@Override
protected Void doInBackground(Void... params)
{
try
{
postData();
}
catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
//dismiss progress dialog
}
}
public void postData()
{
Thread t = new Thread()
{
public void run()
{
Looper.prepare();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://yourURL");
try
{
// Your webservice code......
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Looper.loop(); //Loop in the message queue
}
};
t.start();
}
}
这将解决您的错误...
实际上问题是我从线程调用 Asynctask。
通过使用 runOnUiThread,我从线程调用 Asynctask 解决了我的问题。
mSplashTread = new Thread() {
@Override
public void run() {
try {
int waited = 0;
while (mActive && (waited < mSplashTime)) {
sleep(100);
if (mActive) {
waited += 100;
}
}
} catch (InterruptedException e) {
AppUtil.getInstance().logErrorMessage(TAG, e.getMessage());
} finally {
if (mIsBackPressed) {
finish();
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
GetMobilePremissionWebservice getMobilePermissionWebservice = new GetMobilePremissionWebservice(
mContext, SplashActivity.this);
getMobilePermissionWebservice
.getMobilePermissionInfo();
}
});
}
}
}
};
但我仍然不知道为什么相同的代码在 android 版本 4.2 Samsung s3 中工作。