Reputation: 9044
I have called an Activity method that updates UI from a Fragment and I get a silent CalledFromWrongThreadException
that tells me Only the original thread that created a view hierarchy can touch its views
.
My Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
createDynamicView();
}
public void createDynamicView() {
// Create some View and attach that to a ViewGroup dynamically as below:
RelativeLayout rl = new RelativeLayout(this);
// ...
TextView textView = new TextView(this);
// ...
rl.addView(textView, layout_params1);
layout.addView(rl, layout_params2);
}
// Method called from Fragment
@Override
public void updateLayout() {
View v = layout.getChaildAt(index); // v is a TextView
// This line throws a silent Exception:
// android.view.ViewRootImpl$CalledFromWrongThreadException:
// Only the original thread that created a view hierarchy can touch its views
v.setBackgroundColor(Color.WHITE);
}
Inside fragment:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
parent = (SettingsInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement SettingsInterface");
}
}
public void updateLayout() {
parent.updateLayout();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
webView = (WebView) view.findViewById(R.id.webView1);
// ...
textWebView.addJavascriptInterface(new JSInterface(getActivity()), "Android");
}
public class JSInterface {
@JavascriptInterface
public void updateLayout() {
updateLayout();
}
}
If I put that line inside a runOnUiThread
block as below:
runOnUiThread(new Runnable() {
@Override
public void run() {
v.setBackgroundColor(Color.WHITE);
}
});
I will not get exception but this could may run after first UI update. I want to know that does fragment run in a separate thread than UI thread? and why this exception is silent?
Upvotes: 0
Views: 2008
Reputation: 3145
Fragments and activities are both running on the main UI thread. Your problem is you are calling your updateLayout() method from a JS thread which is NOT your UI thread. And since you cannot modify the UI components from any other thread than the main UI thread, you will get that exception.
Solution: like you said, use runOnUiThread.
Upvotes: 2