2

ハンドラーとランナブルがあり、ランナブルは5秒ごとに画面にトーストを投稿します。コードは次のとおりです。

Handler handler = new Handler();
Runnable runnable = new Runnable() {

    public void run() {

        Toast.makeText(getApplicationContext(), "DISPLAY MESSAGE" + walking, Toast.LENGTH_SHORT).show();
        handler.postDelayed(runnable, 5000);
    }
};

同じアクティビティ内で、kill ボタンを押してコールバックを削除し、次のように呼び出します。

handler.removeCallbacks(runnable);

上記が呼び出されると、トーストの表示が停止するため、これまでのところすべて問題ありません。アクティビティを離れて別のアクティビティに移動すると、トースト メッセージが表示され続けます。これは私が望むものですが、ランナブルが作成された最初のアクティビティに戻ってキル ボタンを押しても、ランナブルは削除されません。出入りするときにランナブルを削除できなくなりました。

SOでハンドラーとランナブルを使用して見たほとんどすべての例を使用してみましたが、これを理解するのに役立つものは何もありませんでした。

アクティビティを離れて戻ったときに、新しい実行可能なオブジェクトとハンドラー オブジェクトが作成される可能性がありますか? もしそうなら、なぜ最初のランナブルが実行を続けるのですか?

4

3 に答える 3

2

アクティビティで長期にわたる参照を保持するのは不適切な形式です。電話を回転させても、それらは簡単かつ頻繁に破壊され、再作成されます! 何が起こっているかというと、Activity が再作成されると、ご想像のとおり、新しい Runnable および Handler オブジェクトが作成されます。

サービスに頼らずにこれを回避するために、Fragment を作成します…これを StateFragment と呼びましょう。

この Fragment に何も表示しないので、ユーザーには見えません。変数を格納するためにのみ使用されます。アクティビティが作成されたら、まだ存在していない場合はアクティビティに追加します。最後に、Fragment クラス自体の onCreate で、RetainInstance を true に設定します。

これはちょっとしたハックであることは認めますが、アクティビティが作成されたり破棄されたりするときにプロセス内の変数を保存するのに非常に便利な方法です。この場合、Activity が破棄されて再作成されると、しばらくの間バックグラウンドにあり、GC によってクリーンアップされない限り、フラグメントは保持される可能性があります。以下のコード:

public class StateFragment extends Fragment{
  //add some variables here
  //these will not last long time!
  Handler handler;
  Runnable runnable;

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

    // Retain this fragment across configuration changes.
    setRetainInstance(true); //<--this is the important part!
        Handler = new Handler... etc.



  }
}

アクティビティで、参照を保持するクラスレベルの変数を用意します。

public Class MainActivity  extends FragmentActivity {
StateFragment sf;

次に、「onCreate」で存在するかどうかを確認し、存在しない場合は添付する必要があります。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sf=(StateFragment) getFragmentManager().findFragmentByTag("storage");
if (sf==null)
{
  sf=new StateFragment();
  getFragmentManager().beginTransaction().add(sf, "storage").commit();
}

一般的に、Activity の揮発性は大きな苦痛であり、より永続的なストレージを持つことは一般的に大きなメリットです。Runnable を次のように簡単に参照できるようになりました。

sf.runnable
于 2013-12-02T12:36:36.210 に答える
1

以下を試してください。5秒ごとに表示するたびにタイマークラスを使用し、Toastクラスからバックヘルパーサービスクラスを開始します。

public class BackHelper extends Service {   
        @Override
        public void onCreate() 
        {
            Log.i(TAG, "Service onCreate");
            super.onCreate();
                        Timer timer = new Timer();
                TimerTask updateProfile = new BackHelper(sock.this);
                    timer.scheduleAtFixedRate(updateProfile, 0, 5000);      
        }
        @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
            Log.i(TAG, "Service onDestroy");
            super.onDestroy();
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO Auto-generated method stub
            Log.i(TAG, "Service onstart");

            return Service.START_STICKY;
        }
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            Log.i(TAG, "Service onBind");
            return null;
        }
    public class sock extends TimerTask
        {
        @Override
            public void run()
            {
     Toast.makeText(getBaseContext(), "DISPLAY MESSAGE" + walking, Toast.LENGTH_SHORT).show();

                    }
            }
于 2013-03-23T01:57:11.990 に答える
1

バックグラウンドで実行されるサービスを実装し、ボタンが押されたときにサービスを強制終了する必要があります。これは、これを実装できる最も簡単な方法です。

于 2013-03-22T18:04:40.193 に答える