Ali Behzadian Nejad
Ali Behzadian Nejad

Reputation: 9044

Does Activity method called from Fragment run in the UI thread?

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

Answers (1)

Kasra
Kasra

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

Related Questions