1

Activity私の Android アプリは、ログインに PhoneGap ベースを使用しています。しかし、ユーザーのログイン後、次のアクティビティでバックグラウンドでタスクを実行します。ただし、ログイン成功メソッドがビューを編集しようとすると (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);
    }
    ...
}

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

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 スレッドで実行されます。

問題は、WebCore スレッドで実行されていることです。つまり、WebCore スレッドでアクティビティgotoMain()を開始しようとしていますが、これは正しくありません。MainNative

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

編集:この問題が発生している可能性もあります。AsyncTask 古いバージョンの Android (Jelly Bean より前) では、クラスがメイン スレッドにロードされていることを確認する必要があります。PhoneGap アプリの設定方法によっては、初めてコードを参照AsyncTaskする (強制的にクラスをロードする) のがバックグラウンド スレッドである可能性があります。これが発生すると、AsyncTaskクラスは本質的に使用できなくなります。私がリンクしている回答を見ると、アプリのどこにでも配置できる1行のコードがあり、(1) 早期に実行され、(2)メインスレッドで実行されることがわかっています...このコードを配置しますメインスレッドでクラスをロードすると、正しいスレッドで強制的にクラスがロードされ、問題が修正されます。

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