我做了一个AsyncTask,它应该编译一个TextView。这是对我所做的事情的简短回顾。我删除了很多行,所以我希望我没有忘记任何东西。
public class MyClass extends RelativeLayout {
private TextView messageTextView;
public MyClass(Context context) {
super(context);
init(context); }
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context); }
public MyClass(Context context, AttributeSet attrs) {
super(context, attrs);
init(context); }
private void init(Context context) {
createLayoutContent();
run();
}
private void createLayoutContent (Context context) {
this.setLayoutParams(new RelativeLayout.LayoutParams (RelativeLayout.LayoutParams.MATCH_PARENT, 0));
messageView = new TextView(context);
messageView.setText("test");
this.addView(messageView);
}
private void start() {
new AsyncTask<Void, String, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
String s_message = "test2";
messageView.setText(s_message); **// HERE IS WHERE THE ERROR IS //**
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
}
在此之后,我将对象直接放在布局中:
<<...>MyClass
android:id="@+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
现在的问题是,在某些应用程序上,这完全有效。一旦活动运行,setContentView(( 就会创建 ui 对象,一切都很好。在其他应用程序上,我不断收到一条错误消息,指出">只有创建视图层次结构的原始线程才能触摸其视图。
我收到此错误,但我不明白为什么在某些应用程序上它工作正常......更奇怪的是,我曾经遇到过通常出错的应用程序突然开始工作,然后在两次正确运行后又回到错误!!
这完全奇怪。
我知道也许细节不足以检测到错误,所以请原谅我,但我检查了我能想到的所有拘留,我找不到它何时有效和何时无效之间的显着差异。也许更多的专家眼睛可以检测到某些东西,解释某些内容或建议我在哪里调试。有人可以帮助我吗?
谢谢。
我不确定为什么它有时有效。但它应该每次都失败。如果 Android 系统决定在 UI 线程中运行您的后台线程代码,则它可能有效。
以下是解决您的问题的方法:将"触摸视图"内容移动到onPostExcution()
或onProgressUpdate()
。UI 只能从 UI 线程内部触摸。AsyncTask非常方便地做到这一点。除doInBackground()
之外的所有AsyncTask's
方法都在 UI 线程上运行。
因此,切勿直接从doInBackground()
更改Views
。
private void start() {
new AsyncTask<Void, String, String>() {
@Override
protected String doInBackground(Void... params) {
try {
String s_message = "test2";
return s_message;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
messageView.setText(s);
}
}.execute();
}