我使用AsyncTask通过互联网获取和上传数据。我想在活动上显示任务的当前状态。要做到这一点,我使用观察者,它将当前状态发送到我的活动。以下是我的Background.java
代码的简短摘要:
private class Syncing extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
sync.init();
if (Sync.isOnline()) {
setChanged();
notifyObservers(ObserverStatus.UPLOAD_PENDING);
sync.upload(); //Upload data
setChanged();
notifyObservers(ObserverStatus.DOWNLOAD_PENDING);
sync.download(); //Download Data
setChanged();
notifyObservers(ObserverStatus.SYNC_COMPLETED);
} else {
setChanged();
notifyObservers(ObserverStatus.OFFLINE);
}
return "Executed";
}
@Override
protected void onPostExecute(String result) {
setChanged();
notifyObservers(ObserverStatus.FINISHED);
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
此Syncing
类嵌入在Background
类中。在我使用第二次notifyObservers()
调用之前,此代码没有任何问题。所以在这种情况下,如果用户在线并启动任务,将调用第一个notifyObservers()
,但第二个,第三个......将不会被调用,它会抛出以下错误:
05-10 21:50:21.563 16265-16285/net.myapp.example E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: net.myapp.example, PID: 16265
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:325)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6892)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1083)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5205)
at android.view.View.invalidateInternal(View.java:13656)
at android.view.View.invalidate(View.java:13620)
at android.view.View.invalidate(View.java:13604)
at android.widget.ImageView.setImageDrawable(ImageView.java:531)
at net.myapp.example.MainActivity.update(MainActivity.java:239)
at java.util.Observable.notifyObservers(Observable.java:161)
at net.myapp.example.sync.Background$Syncing.doInBackground(Background.java:37)
at net.myapp.example.sync.Background$Syncing.doInBackground(Background.java:27)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
在我的活动的第238行,将替换一个图标,您也可以在错误日志中看到。但它将在第37行发生。这是第二个notifyObservers()
将被调用的地方。
我该如何解决这个问题?
答案 0 :(得分:1)
我现在找到了一个解决此问题的方法。我现在使用onProgressUpdate
。所以我添加了以下功能:
@Override
protected void onProgressUpdate(ObserverStatus... values) {
super.onProgressUpdate(values);
setChanged();
notifyObservers(values[0]);
}
现在我可以通过publishProgress()
方法发送进度了。幸运的是它非常好。
@Override
protected String doInBackground(String... params) {
sync.init();
if (Sync.isOnline()) {
publishProgress(ObserverStatus.UPLOAD_PENDING);
sync.upload(); //Upload data
publishProgress(ObserverStatus.DOWNLOAD_PENDING);
sync.download(); //Download Data
publishProgress(ObserverStatus.SYNC_COMPLETED);
} else {
setChanged();
notifyObservers(ObserverStatus.OFFLINE);
}
return "Executed";
}
感谢您的回答@jereksel。
答案 1 :(得分:0)
在Android视图上,相关属性只能在UI线程中更改。在无法执行此操作的后台线程上调用doInBackground
。要解决此问题,您应该在notifyObservers
(docs)函数中包含runOnUiThread
个内容。