2

ICS デバイスで非常に奇妙な動作が発生しています。レイアウトにボタンがあり、次のようにリスナーをクリックします。

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button b = (Button) findViewById(R.id.button1);
    b.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
        // To just demonstrate weird behavior, i am throwing run-time exception 
         throw new RuntimeException("testing weird behavior on ICS");

         //String s = null;   s.length(); You can try this , application does not crash.
        } 
    });
}

通常の状態では、これによりアプリケーションがクラッシュするはずですが、驚くべきことに、次のように logcat でクラッシュが見られますが、アプリケーションはクラッシュしません。むしろ見える

Failed to handle callback; interface not implemented, callback:android.view.View$PerformClick@40d80cc8
java.lang.RuntimeException: testing weird  behaviour
     at com.example.sampleproject.MainActivity$1.onClick(MainActivity.java:21)
     at android.view.View.performClick(View.java:3538)
     at android.view.View$PerformClick.run(View.java:14330)
     at android.os.Handler.handleCallback(Handler.java:608)
     at android.os.Handler.dispatchMessage(Handler.java:92)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:4977)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:511)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
     at dalvik.system.NativeStart.main(Native Method)

なぜ私がこの奇妙な振る舞いを経験しているのか、どんな助けも大歓迎です。

@Jenの提案に従って、 b.performClick(); を試しました。、アプリケーションは通常の動作を示しますが、 onClickListener では同じ動作を示します。

私はここにバグを提出しました リンク http://code.google.com/p/android/issues/detail?id=35517&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

4

1 に答える 1

0

ボタンbがnullかどうかを確認していますか? logcat が述べているjava.lang.NullPointerExceptionように、問題が発生しているのは奇妙ですが、私が通常持っているのは次のとおりです。

_btnFoo = (Button)findViewById(R.id.btnFoo);
if (_btnFoo != null){
   _btnFoo.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v){
         ....
      }
   });
}

痛い親指のように突き出ているのはヌルポインター例外であるため、その周りで何かが初期化されていません。

編集: 私の答えは十分ではなかったので、ICS 4.0.3リポジトリから取得したソースを掘り下げることを考えました。これは、ここにあるコードのセクションです。frameworks/base/core/java/android/view/View.java

private final class PerformClick implements Runnable {
    public void run() {
        performClick();
    }
}

このメソッドの要点は、同じソースの 3505 行目にあります。

public boolean performClick() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            return true;
        }

        return false;
    }

私の推測では、Runnable内部はグリッチがあると思われます。これは、ヒントや同様PerformClickのセーフガードなしでクロススレッディングしているように見えるためです。runOnUiThread

前の文で強調しておきますが、自由回答の疑問符を付けて、文字どおりに解釈しないで、単語の意味で大まかに使用します。

Jen のコメントは、ここに示すように、3010 行目から正しいことが証明されています。

case R.styleable.View_onClick:
    if (context.isRestricted()) {
        throw new IllegalStateException("The android:onClick attribute cannot "
                + "be used within a restricted context");
    }

    final String handlerName = a.getString(attr);
    if (handlerName != null) {
        setOnClickListener(new OnClickListener() {
            private Method mHandler;

            public void onClick(View v) {
                if (mHandler == null) {
                    try {
                        mHandler = getContext().getClass().getMethod(handlerName,
                                View.class);
                    } catch (NoSuchMethodException e) {
                        int id = getId();
                        String idText = id == NO_ID ? "" : " with id '"
                                + getContext().getResources().getResourceEntryName(
                                    id) + "'";
                        throw new IllegalStateException("Could not find a method " +
                                handlerName + "(View) in the activity "
                                + getContext().getClass() + " for onClick handler"
                                + " on view " + View.this.getClass() + idText, e);
                    }
                }

                try {
                    mHandler.invoke(getContext(), View.this);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Could not execute non "
                            + "public method of the activity", e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException("Could not execute "
                            + "method of the activity", e);
                }
            }
        });
    }
    break;

行 3452 で、setOnClickListenerメソッドは次のようにコールバックが登録される場所です。

public void setOnClickListener(OnClickListener l) {
    if (!isClickable()) {
        setClickable(true);
    }
    getListenerInfo().mOnClickListener = l;
}

OPの質問に対する答えは、Jensが簡潔に述べたように、フレームワークにバグがあるということです。少なくともエラー処理の不一致です。通常、例外をスローするべきではありませんがonClick、クリック ハンドラーで多くの作業を行うアプリで強制終了が報告されない場合、「実際に」エラーを追跡するのが少し難しくなると想像できます。 .

于 2012-07-25T20:16:29.950 に答える