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

时间:2015-01-31 20:23:21

标签: android multithreading android-fragments ui-thread

我调用了一个从Fragment更新UI的Activity方法,然后我得到一个告诉我CalledFromWrongThreadException的无声Only the original thread that created a view hierarchy can touch its views

我的活动:

@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线程? 为什么这个例外是沉默的?

1 个答案:

答案 0 :(得分:2)

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

解决方案:就像你说的那样,使用runOnUiThread。