CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图

时间:2013-06-14 20:01:05

标签: android multithreading exception

在我的应用程序中,我使用自定义库来加载svg文件,并且加载过程有点贵,所以我试图将其移动到另一个线程中。我得到“CalledFromWrongThreadException”。根据这里的例子:http://developer.android.com/guide/components/processes-and-threads.html#Threads一切都必须正常,但我仍然收到错误。我缺少什么?

public class SinglePhraseFragment extends Fragment {

View rootView;
String imageFileName;
int in_favorites, id;
SpannableString phrase;

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    rootView = (ViewGroup) inflater.inflate(R.layout.single_phrase_layout, container, false);


    new Thread(new Runnable() {
        public void run() {
            //loading svg file and converting it into drawable
            SVG svg = null;
            try {
                final ImageView phraseImage = (ImageView) rootView.findViewById(R.id.phraseImage);
                svg = SVGParser.getSVGFromAsset(getActivity().getAssets(), imageFileName); //loading svg file
                final Drawable drawable = svg.createPictureDrawable(); //creating drawable from svg
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
                    phraseImage.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

                //trying to set drawable to ImageView and getting error
                phraseImage.post(new Runnable() {
                    public void run() {
                        phraseImage.setImageDrawable(drawable);
                    }
                });
            }
            catch (IOException e) {}
            catch (SVGParseException e) {}
        }
    }).start();

    return rootView;
}

所以我编辑了代码:

public class SinglePhraseFragment extends Fragment {

View rootView;
String imageFileName;
int in_favorites, id;
SpannableString phrase;

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    rootView = (ViewGroup) inflater.inflate(R.layout.single_phrase_layout, container, false);


    new Thread(new Runnable() {
        public void run() {
            //loading svg file and converting it into drawable
            SVG svg = null;
            try {
                final ImageView phraseImage = (ImageView) rootView.findViewById(R.id.phraseImage);
                svg = SVGParser.getSVGFromAsset(getActivity().getAssets(), imageFileName); //loading svg file
                final Drawable drawable = svg.createPictureDrawable(); //creating drawable from svg
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
                    phraseImage.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

                //trying to set drawable to ImageView and getting error
                getActivity().runOnUiThread(new Runnable() {
                    public void run() {
                        phraseImage.setImageDrawable(drawable);
                    }
                });
            catch (IOException e) {Log.e("app", "IOException");}
            catch (SVGParseException e) {Log.e("app", "SVGParseException");}
        }
    }).start();

    return rootView;
}

这是logCat输出:

06-14 23:11:33.476: W/dalvikvm(8270): threadid=11: thread exiting with uncaught exception (group=0x40abb228)
06-14 23:11:33.486: E/AndroidRuntime(8270): FATAL EXCEPTION: Thread-39961
06-14 23:11:33.486: E/AndroidRuntime(8270): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4132)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.ViewRootImpl.invalidateChild(ViewRootImpl.java:736)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:785)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:4013)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.View.invalidate(View.java:8614)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at android.view.View.setLayerType(View.java:10128)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at com.potatopit.pick_app.SinglePhraseFragment$2.run(SinglePhraseFragment.java:74)
06-14 23:11:33.486: E/AndroidRuntime(8270):     at java.lang.Thread.run(Thread.java:864)

2 个答案:

答案 0 :(得分:1)

当堆栈跟踪告诉您时,您正试图在后台线程上调用setLayerType()。请在主应用程序主题上执行此操作,例如您在Runnable使用的runOnUiThread()内。

顺便说一句,您可能希望使用AsyncTask来获得更清晰的代码,而不是当前的Thread - 和 - runOnUiThread()实施。

答案 1 :(得分:0)

您似乎正在从后台线程更新ui。你需要在主ui线程上更新ui。

使用runOnUiThread

      getActivity().runOnUiThread(new Runnable(){
          public void run() 
          { 
              phraseImage.setImageDrawable(drawable);            
          }
     });