1

我的 android 应用程序使用基于 PhoneGap 的Activity登录。但是在用户登录后,在下一个活动中,我在后台运行了一个任务。但是当登录成功方法尝试编辑视图时(PhoneGap 活动关闭后),它总是抛出

android.view.ViewRoot$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图。

我的代码是:

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

在 MainNative 类中,我编写了一个在后台运行的任务

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);
    }
    ...
}

监视列表助手:

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

来自 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)
4

1 回答 1

3

在此处查看此 PhoneGap 文档

穿线

WebView 中的 JavaScript 不在 UI 线程上运行。它在 WebCore 线程上运行。execute 方法也在 WebCore 线程上运行。

问题是gotoMain()正在 WebCore 线程上运行,这意味着您正在尝试MainNative在 WebCore 线程上启动活动,这是不正确的

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

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

编辑:你也有可能遇到这个问题。在旧版本的 Android 中(在 Jelly Bean 之前),有必要确保AsyncTask 该类已加载到主线程上。根据您的 PhoneGap 应用程序的设置方式,您的代码第一次引用AsyncTask(强制加载类)可能在后台线程上。如果发生这种情况,AsyncTask该类将基本上无法使用。如果您查看我链接到的答案,您可以将一行代码放在应用程序中的任何位置(1)提前运行,并且(2)您知道在线程上运行......放置此代码然后在主线程上将强制类加载到正确的线程上,并解决问题。

Class.forName("android.os.AsyncTask");
于 2013-06-21T09:51:35.927 回答