0

一部のデバイスで、新しいアクティビティを開始するときに ANR が発生するバグがあります。私のデバイス (Samsung Galaxy S2) にはわずかな遅延がありますが、ANR はまったく得られません。時々 ANR を取得する他のデバイスは、HTC Desire HD と Xperia (私が知っている) です。古い携帯電話が新しい携帯電話よりも遅くなるのは、私がやっているある種のCPU集約的なことかもしれないと思っていますが、わかりません. 私は Asynctask を使用してすべての重いものをロードしていますが、UI スレッドは実際にはあまり機能しません。

コードはこちら

ここに別のスレッドを作成して、共有設定にアクセスします。

  @Override
    protected void onResume() {
        super.onResume();
        sound = false;
        Thread prefThread = new Thread(new Runnable(){
            public void run(){
                SharedPreferences prefs = getSharedPreferences(SharedPrefValues.OPTION_PREF, Context.MODE_PRIVATE);
                sound = prefs.getBoolean("sound", true);
                String difficulty = prefs.getString(SharedPrefValues.DIFFICULTY, SharedPrefValues.DIF_MEDIUM);
                prefs = getSharedPreferences(SharedPrefValues.HIGHSCORE_PREF, Context.MODE_PRIVATE);
                for(int i = 0; i < mapPnl.buttons.size(); i++)
                    mapPnl.SetRank(mapPnl.buttons.get(i), prefs.getString(SharedPrefValues.HIGHSCORE_RANK_NAME + difficulty + mapPnl.buttons.get(i).getName(), SharedPrefValues.RANK_NOT_OK));

            }
        });
        prefThread.start();
        mapPnl.speedX = 0;
    }

bgTask は AsyncTask です。

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                WindowManager.LayoutParams.FLAG_FULLSCREEN); 


        Display display = getWindowManager().getDefaultDisplay();
        screenSize = new Point();
        screenSize.x = display.getWidth();
        screenSize.y = display.getHeight();


        mapPnl = new MapPnl(this);

        LoadBitmapsStuff bgTask = new LoadBitmapsStuff(this);
        bgTask.execute();

        addContentView(mapPnl, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    }

これは、すべてを描画し、onTouchEvents を処理する Surfaceview です。

private class MapPnl extends SurfaceView implements SurfaceHolder.Callback{
...
public MapPnl(Context context) {
            super(context);
            getHolder().addCallback(this);

            buttons = new ArrayList<ButtonMap>();

            posX = 0;
            speedX = 0;
            maxX = 0;

            drawThread = new DrawThread(getHolder());
            drawThread.setRunning(true);
        }
....
}

surfaceCreated で drawThread を開始します

    public void surfaceCreated(SurfaceHolder arg0) {
        if(drawThread.getState() == Thread.State.NEW)
            drawThread.start();
        else if(drawThread.getState() == Thread.State.TERMINATED){
            drawThread = new DrawThread(getHolder());
            drawThread.setRunning(true);
            drawThread.start();
        }
    }

ウェブ上のガイドから表面破壊された

    public void surfaceDestroyed(SurfaceHolder arg0) {
        boolean retry = true;
        drawThread.setRunning(false);
        while (retry) {
            try {
                drawThread.join();
                retry = false;
            } catch (InterruptedException e) {
                // we will try it again and again...
            }
        }

    }

重要なコードだと思います。私が知る限り、UIthread は私が示したこれらの部分のみを実行します (ondestroy ではないかもしれませんが、誰かが別のスレッドでその部分に問題を抱えていることを読みました)。そして、それはほとんどのシステムでかなり高速に実行されるはずです.

asyncTask の実行が完了するまで、drawthread は「読み込み中」というテキストのみを表示します。したがって、すべてが読み込まれて描画されると、ユーザーは画面に触れ始め、ANR が表示されます。任意のヒント?

更新(12-05-18): エミュレータから logcat を取得できました。遅いコンピューターを使用しましたが、高速のコンピューターを使用すると、ANR が表示されませんでした。

PID 860 はアクティビティです

03-31 01:41:03.453: I/Process(71): Sending signal. PID: 860 SIG: 3
03-31 01:41:03.453: I/dalvikvm(860): threadid=3: reacting to signal 3
03-31 01:41:03.672: I/dalvikvm(860): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:03.672: I/Process(71): Sending signal. PID: 71 SIG: 3
03-31 01:41:03.682: I/dalvikvm(71): threadid=3: reacting to signal 3
03-31 01:41:03.992: I/dalvikvm(71): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:03.992: I/Process(71): Sending signal. PID: 381 SIG: 3
03-31 01:41:03.992: I/dalvikvm(381): threadid=3: reacting to signal 3
03-31 01:41:04.212: I/Process(71): Sending signal. PID: 349 SIG: 3
03-31 01:41:04.212: I/dalvikvm(349): threadid=3: reacting to signal 3
03-31 01:41:04.322: I/dalvikvm(349): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:04.332: I/Process(71): Sending signal. PID: 664 SIG: 3
03-31 01:41:04.364: I/dalvikvm(664): threadid=3: reacting to signal 3
03-31 01:41:04.542: I/Process(71): Sending signal. PID: 364 SIG: 3
03-31 01:41:04.612: I/dalvikvm(364): threadid=3: reacting to signal 3
03-31 01:41:04.744: I/Process(71): Sending signal. PID: 371 SIG: 3
03-31 01:41:04.953: I/Process(71): Sending signal. PID: 822 SIG: 3
03-31 01:41:05.162: I/Process(71): Sending signal. PID: 139 SIG: 3
03-31 01:41:05.162: I/dalvikvm(139): threadid=3: reacting to signal 3
03-31 01:41:05.221: I/dalvikvm(822): threadid=3: reacting to signal 3
03-31 01:41:05.292: I/dalvikvm(371): threadid=3: reacting to signal 3
03-31 01:41:05.312: I/dalvikvm(139): Wrote stack traces to '/data/anr/traces.txt'
03-31 01:41:05.402: E/ActivityManager(71): ANR in se.blogspot.developingjsa.view (se.blogspot.developingjsa.view/.FirstMenu)
03-31 01:41:05.402: E/ActivityManager(71): Reason: keyDispatchingTimedOut
03-31 01:41:05.402: E/ActivityManager(71): Load: 1.79 / 1.63 / 1.31
03-31 01:41:05.402: E/ActivityManager(71): CPU usage from 5383ms to 64ms ago:
03-31 01:41:05.402: E/ActivityManager(71):   elopingjsa.view: 51% = 49% user + 1% kernel / faults: 36 minor 7 major
03-31 01:41:05.402: E/ActivityManager(71):   system_server: 44% = 41% user + 3% kernel / faults: 133 minor 1 major
03-31 01:41:05.402: E/ActivityManager(71):   adbd: 1% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   m.android.phone: 1% = 0% user + 0% kernel / faults: 112 minor
03-31 01:41:05.402: E/ActivityManager(71):   ronsoft.openwnn: 0% = 0% user + 0% kernel / faults: 22 minor
03-31 01:41:05.402: E/ActivityManager(71):   com.svox.pico: 0% = 0% user + 0% kernel / faults: 7 minor
03-31 01:41:05.402: E/ActivityManager(71):   logcat: 0% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   qemud: 0% = 0% user + 0% kernel
03-31 01:41:05.402: E/ActivityManager(71):   id.defcontainer: 0% = 0% user + 0% kernel / faults: 6 minor
03-31 01:41:05.402: E/ActivityManager(71):   ackageinstaller: 0% = 0% user + 0% kernel / faults: 5 minor
03-31 01:41:05.402: E/ActivityManager(71): TOTAL: 100% = 91% user + 8% kernel + 0% irq + 0% softirq
4

1 に答える 1

0

その解決しました。

Google Play を使用して、これらのデバイスからスタック トレースを取得できました。そこに投稿したコードに問題はなかったことがわかりました。

チュートリアルのコードを使用していました ( http://www.droidnova.com/playing-with-graphics-in-android-part-i,147.html )。そのコードは、onTouchEvent が発生するたびに、drawThread から surfaceHolder を取得しようとしていました。

drawThread がループ内にあり、UiTread がそれを取得しようとしたときに surfaceHolder を解放できず、ANR が発生したことがあると思います。

于 2012-05-18T16:07:53.637 に答える