我已经阅读了所有与此有关的问题。而且情况也不一样。相信我。
我知道AsyncTask doInBackground函数具有自己的线程,您必须在onPreExecute和onPostExecute中触摸视图。
此外,我正在使用isCancelled和isFinishing来确保任务仍然有效。有了所有这些东西,该应用程序仍然崩溃。
这是代码:
public class MainActivity {
private Activity activity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Main);
activity = this;
new MyTask(activity).execute();
}
private class MyTask extends AsyncTask<Void, Void, User[]> {
// ...
@Override
protected void onPreExecute() {
}
@Override
protected User[] doInBackground(String... params) {
// Api call
// return results
}
@Override
protected void onPostExecute(User[] users) {
if (isCancelled() || isFinishing()) return;
findViewById(R.id.panelViews).removeAllViews();
findViewById(R.id.element).setText("something");
// ... more
}
}
}
如你看到的:
视图的触摸位于onPostExecute中
如果用户取消退出屏幕的任务,我会使用“ isCancelled”
与“ isFinishing”相同
甚至现在,当我尝试更改视图的某些内容时(在示例中为简单文本),该行中仍然出现错误“只有创建视图层次结构的原始线程才能触摸其视图”。
如果我在尝试获取API结果时取消(例如按回去)就可以了,并且可以正常工作。
如果我恰好在API结果到达时取消了它,并且在它开始更改之前,它崩溃了(我在onPostExecute中插入了“ sleep”以完成此测试)。
错误代码在第112行中,即“ findViewById(R.id.panelViews).removeAllViews();”。如上所述:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2988)
at android.view.ViewRoot.requestLayout(ViewRoot.java:648)
at android.view.View.requestLayout(View.java:8416)
at android.view.View.requestLayout(View.java:8416)
at android.view.View.requestLayout(View.java:8416)
at android.view.View.requestLayout(View.java:8416)
at android.view.View.requestLayout(View.java:8416)
at android.widget.ScrollView.requestLayout(ScrollView.java:1303)
at android.view.View.requestLayout(View.java:8416)
at android.view.View.requestLayout(View.java:8416)
at android.view.ViewGroup.removeAllViews(ViewGroup.java:2354)
at com.test.activities.MainActivity$MyTask.onPostExecute(MainActivity.java:112)
at com.test.activities.MainActivity$MyTask.onPostExecute(MainActivity.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:417)
at android.os.AsyncTask.access$300(AsyncTask.java:127)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.os.HandlerThread.run(HandlerThread.java:60)
最佳答案
查看调用堆栈,以下调用表明AsyncTask类已在非UI线程上加载。at android.os.HandlerThread.run(HandlerThread.java:60)
AsyncTask reference documentation中提到的线程规则之一是:
必须在UI线程上加载AsyncTask类。这个做完了
从JELLY_BEAN开始自动生成。
这是与此issue相关的错误。
解决方案之一是在AsyncTask
方法中手动加载Application onCreate
类。这样可以确保在任何应用程序组件使用该类之前,将该类加载到主线程上。
public class MyApplication extends Application {
@Override
public void onCreate() {
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
}
super.onCreate();
}
}
请记住在
MyApplication
文件中指定AndroidManifest
。