Activity 方法是否在 UI 线程中从 Fragment 运行 调用?

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

我调用了一个 Activity 方法来更新 UI 从一个片段,我得到一个静默的 CalledFromWrongThreadException 告诉我 Only the original thread that created a view hierarchy can touch its views

我的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);
}

内部片段:

@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();
    }
}

如果我将该行放在 runOnUiThread 块中,如下所示:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        v.setBackgroundColor(Color.WHITE);
    }
});

我不会得到异常,但这可能会在第一次 UI 更新后 运行。 我想知道片段 运行 是否在单独的线程中而不是 UI 线程中? 为什么这个例外是沉默的?

片段和活动都 运行 在主 UI 线程上。你的问题是你从一个 JS 线程调用你的 updateLayout() 方法,它不是你的 UI 线程。由于除了主 UI 线程之外,您不能从任何其他线程修改 UI 组件,因此您将得到该异常。

解决方案:如你所说,使用runOnUiThread。