1. ホーム
  2. android

[解決済み] Androidでスレッドやプロセスを一時停止/スリープさせる方法は?

2022-02-10 07:23:11

質問

2行のコードの間に間を作りたいのですが、少し説明させてください。

-> ユーザーがボタン(実際にはカード)をクリックするので、このボタンの背景を変えることで表示しています。

thisbutton.setBackgroundResource(R.drawable.icon);

->例えば1秒後に、ボタンの背景を元に戻して、前の状態に戻す必要があります。

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> で、この2行のコードの間にスレッドを一時停止してみました。

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

しかし、これではうまくいきません。もしかしたら、一時停止が必要なのはThreadではなくプロセスなのでしょうか?

もやってみました(でもうまくいきません)。

new Reminder(5);

これを使って

public class Reminder {

Timer timer;

        public Reminder(int seconds) {
            timer = new Timer();
            timer.schedule(new RemindTask(), seconds*1000);
        }

        class RemindTask extends TimerTask {
            public void run() {
                System.out.format("Time's up!%n");
                timer.cancel(); //Terminate the timer thread
            }
        }  
    }

スレッドやプロセスを一時停止/スリープさせるには?

解決方法は?

この問題の解決策の1つは ハンドラ.postDelayed() メソッドを使用します。一部のGoogle トレーニング教材 も同様の解決策を提案しています。

@Override
public void onClick(View v) {
    my_button.setBackgroundResource(R.drawable.icon);

    Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() {
         @Override 
         public void run() { 
              my_button.setBackgroundResource(R.drawable.defaultcard); 
         } 
    }, 2000); 
}

しかし、上記の解決策を指摘する声もあります。 メモリリークを引き起こす なぜなら、非静的な内部クラスと匿名クラスを使用しており、その外部クラスであるアクティビティへの参照を暗黙的に保持しているからです。 これは、アクティビティコンテキストがガベージコレクションされるときに問題となります。

メモリリークを回避する、より複雑な解決法は HandlerRunnable というのは、静的な内部クラスはその外部クラスへの暗黙の参照を保持しないため、アクティビティ内の静的な内部クラスと一緒に使用することができます。

private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();

public static class MyRunnable implements Runnable {
    private final WeakReference<Activity> mActivity;

    public MyRunnable(Activity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void run() {
        Activity activity = mActivity.get();
        if (activity != null) {
            Button btn = (Button) activity.findViewById(R.id.button);
            btn.setBackgroundResource(R.drawable.defaultcard);
        }
    }
}

private MyRunnable mRunnable = new MyRunnable(this);

public void onClick(View view) {
    my_button.setBackgroundResource(R.drawable.icon);

    // Execute the Runnable in 2 seconds
    mHandler.postDelayed(mRunnable, 2000);
}

ただし Runnable を使用しています。 弱いリファレンス これは、UIにアクセスする必要のある静的なクラスで必要です。