0

在我的应用程序中,我使用自定义库来加载 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)
4

2 回答 2

1

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

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

于 2013-06-14T20:23:14.777 回答
0

看来您正在从后台线程更新 ui。您需要在主 ui 线程上更新 ui。

使用 runOnUiThread

      getActivity().runOnUiThread(new Runnable(){
          public void run() 
          { 
              phraseImage.setImageDrawable(drawable);            
          }
     }); 
于 2013-06-14T20:16:51.070 回答