CalledFromWrongThreadException修改使用基于PhoneGap的活动视图 [英] CalledFromWrongThreadException modifying a view using PhoneGap based Activity

查看:190
本文介绍了CalledFromWrongThreadException修改使用基于PhoneGap的活动视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Andr​​oid应用程序使用基于PhoneGap的活动登录。但用户登录后,在接下来的活动中,我在后台运行的任务。但是,当登录成功方法试图编辑视图(PhoneGap的活动被关闭后),它总是抛出


  

android.view.ViewRoot $ CalledFromWrongThreadException:只有创建视图层次可以触摸其观点原来的线程


我的code是:

  // BeginActivity延伸DroidGap
公共类BeginLoginActivity扩展BeginActivity
{
    @覆盖
    保护字符串getFirstUrl(){
        意向意图= getIntent();
        字符串pageState = intent.getStringExtra(SplashActivity.EXTRA_PAGE_STATE);        如果(pageState == NULL){
            pageState =登录;
        }        返回文件:///android_asset/www/login.html#+ pageState;
    }    //通过JavaScript在调用的login.html
    公共无效gotoMain(){
        意向意图=新意图(这一点,MainNative.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(意向);
        完();
    }
}

在MainNative课,我code,它在后台运行一个任务

 公共类MainNative延伸活动{
    ...
    公共无效loadItems(){
        ...
        新WatchlistHelper(本).execute(getItemId());
    }    公共无效setWatchedStatus(布尔_true){
        //这正是WebViewCoreThread被抛出,
        //每当PhoneGap的基于活动previously已经打开
        //它运行良好,如果没有PhoneGap的活动已经运行
        watchlistButton_.setImageResource(_true?R.drawable.native_rating_important
                :R.drawable.native_rating_not_important);
        watchlistButton_.setTag(_true);
        watchlistButton_.setVisibility(可见);
        watchlistLoading_.setVisibility(GONE);
    }
    ...
}

WatchlistHelper:

 公共静态类WatchlistHelper扩展的AsyncTask<弦乐,太虚,布尔>
{
    私人MainNative mContext_;    ...    @覆盖
    保护布尔doInBackground(字符串... _ids){
        //我的code,在后台运行
        返回IsTrue运算;
    }    @覆盖
    保护无效onPostExecute(布尔_isTrue){
        mContext_.setWatchedStatus(_isTrue);
    }
}

从logcat的日志:

  14 06-21:45:57.462:E / AndroidRuntime(265):致命异常:WebViewCoreThread
06-21 14:45:57.462:E / AndroidRuntime(265):$ android.view.ViewRoot CalledFromWrongThreadException:只有创建视图层次可以触摸其观点原来的线程。
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.ViewRoot.checkThread(ViewRoot.java:2802)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.ViewRoot.requestLayout(ViewRoot.java:594)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.widget.ScrollView.requestLayout(ScrollView.java:1200)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.widget.ImageView.setImageResource(ImageView.java:275)
06-21 14:45:57.462:E / AndroidRuntime(265):在com.posaurus.android.elements.MainNative.setWatchedStatus(MainNative.java:160)
06-21 14:45:57.462:E / AndroidRuntime(265):在com.posaurus.android.elements.MainNative $ WatchlistHelper.onPostExecute(MainNative.java:205)
06-21 14:45:57.462:E / AndroidRuntime(265):在com.posaurus.android.elements.MainNative $ WatchlistHelper.onPostExecute(MainNative.java:1)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.os.AsyncTask.finish(AsyncTask.java:417)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.os.AsyncTask.access $ 300(AsyncTask.java:127)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.os.AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:429)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.os.Handler.dispatchMessage(Handler.java:99)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.os.Looper.loop(Looper.java:123)
06-21 14:45:57.462:E / AndroidRuntime(265):在android.webkit.WebViewCore $ WebCoreThread.run(WebViewCore.java:621)
06-21 14:45:57.462:E / AndroidRuntime(265):在java.lang.Thread.run(Thread.java:1096)


解决方案

请参阅的这PhoneGap的文档这里


  

线程


  
  

JavaScript中的web视图没有在UI线程上运行。它运行在
  在WebCore的线程。 execute方法还运行在的WebCore
  主题。


问题是, gotoMain()正在的WebCore的线程,这意味着你要开始 MainNative 的WebCore的线程上活动,这是不正确

您应该能够通过修改 gotoMain()的方法,以确保它不会在UI线程的工作来解决这个问题:

 公共无效gotoMain(){
    在UI线程上运行// code:
    runOnUiThread(新的Runnable(){
        公共无效的run(){
            意向意图=新意图(BeginLoginActivity.this,MainNative.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(意向);
            完();
        }
    });
}


编辑:它也有可能是你正在运行了这个问题。在旧版本的Andr​​oid(果冻豆之前),有必要确保在的AsyncTask 加载在主线程上。有了这样你的PhoneGap的应用程序是安装,它可能是你的code引用的AsyncTask (强制类加载)第一次是在后台线程。如果发生这种情况,的AsyncTask 类将基本上无法使用。如果你看一下我链接到的答案,还有一行一块code,你可以把任何地方在您的应用程序:(1)早期运行;(2)你知道的主运行线程...这将code中的主线程上,然后将强制在正确的线程类加载,并解决问题。

 的Class.forName(android.os.AsyncTask);

My android app uses a PhoneGap-based Activity for login. But after the user login, in the next activity, I run a task in the background. But when the login success method is trying to edit a view (after the PhoneGap activity is closed), it always throws

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

My code is:

// BeginActivity extends DroidGap
public class BeginLoginActivity extends BeginActivity 
{
    @Override
    protected String getFirstUrl() {
        Intent intent = getIntent();
        String pageState = intent.getStringExtra(SplashActivity.EXTRA_PAGE_STATE);

        if (pageState == null) {
            pageState = "login";
        }

        return "file:///android_asset/www/login.html#" +pageState;
    }

    //invoked at login.html via javascript
    public void gotoMain() {
        Intent intent = new Intent(this, MainNative.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        finish();
    }
}

In MainNative class, I code a task that runs in the background

public class MainNative extends Activity {
    ...
    public void loadItems() {
        ...
        new WatchlistHelper (this).execute(getItemId());
    }

    public void setWatchedStatus(Boolean _true) {
        // this is where the WebViewCoreThread is thrown, 
        // whenever a phonegap based Activity previously has been opened
        // and it run well if there's no phonegap Activity has run
        watchlistButton_.setImageResource(_true ? R.drawable.native_rating_important
                : R.drawable.native_rating_not_important);
        watchlistButton_.setTag(_true);
        watchlistButton_.setVisibility(VISIBLE);
        watchlistLoading_.setVisibility(GONE);
    }
    ...
}

WatchlistHelper :

public static class WatchlistHelper extends AsyncTask<String, Void, Boolean> 
{
    private MainNative mContext_;

    ...

    @Override
    protected Boolean doInBackground(String... _ids) {
        // My code that run in background
        return isTrue;
    }

    @Override
    protected void onPostExecute(Boolean _isTrue) {
        mContext_.setWatchedStatus(_isTrue);
    }
}

The logs from logcat:

06-21 14:45:57.462: E/AndroidRuntime(265): FATAL EXCEPTION: WebViewCoreThread
06-21 14:45:57.462: E/AndroidRuntime(265): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.ViewRoot.requestLayout(ViewRoot.java:594)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.widget.ScrollView.requestLayout(ScrollView.java:1200)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.view.View.requestLayout(View.java:8125)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.widget.ImageView.setImageResource(ImageView.java:275)
06-21 14:45:57.462: E/AndroidRuntime(265):  at com.posaurus.android.elements.MainNative.setWatchedStatus(MainNative.java:160)
06-21 14:45:57.462: E/AndroidRuntime(265):  at com.posaurus.android.elements.MainNative$WatchlistHelper.onPostExecute(MainNative.java:205)
06-21 14:45:57.462: E/AndroidRuntime(265):  at com.posaurus.android.elements.MainNative$WatchlistHelper.onPostExecute(MainNative.java:1)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.os.AsyncTask.finish(AsyncTask.java:417)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.os.AsyncTask.access$300(AsyncTask.java:127)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.os.Looper.loop(Looper.java:123)
06-21 14:45:57.462: E/AndroidRuntime(265):  at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:621)
06-21 14:45:57.462: E/AndroidRuntime(265):  at java.lang.Thread.run(Thread.java:1096)

解决方案

See this PhoneGap document here:

Threading

JavaScript in the WebView does not run on the UI thread. It runs on the WebCore thread. The execute method also runs on the WebCore thread.

The problem is that gotoMain() is being run on the WebCore thread, which means you're trying to start the MainNative activity on the WebCore thread, which is incorrect.

You should be able to fix this by modifying your gotoMain() method to make sure it does its work on the UI thread:

public void gotoMain() {
    // run code on the UI thread:
    runOnUiThread(new Runnable() {
        public void run() {
            Intent intent = new Intent(BeginLoginActivity.this, MainNative.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
            finish();
        }
    });
}


Edit: it's also possible that you are running into this problem. In older versions of Android (before Jelly Bean), it's necessary to make sure that the AsyncTask class is loaded on the main thread. With the way your PhoneGap app is setup, it's possible that the first time your code references AsyncTask (forcing the class to be loaded) is on a background thread. If this happens, the AsyncTask class will essentially be unusable. If you look at the answer I link to, there is a one line piece of code that you can put anywhere in your app that (1) runs early, and (2) you know runs on the main thread ... placing this code on the main thread will then force class loading on the correct thread, and fix the problem.

Class.forName("android.os.AsyncTask");

这篇关于CalledFromWrongThreadException修改使用基于PhoneGap的活动视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆