0

以下は、更新ボタンと停止ボタンの 1 つだけが表示される 2 つのボタンを持つ Android アクティビティのサンプル コードです。

このコードは次のことを行います。

[更新] をクリックすると、いくつかの AsyncTask が開始されます。タスクの preExecute により、更新ボタンが非表示になり、停止ボタンが表示されます。タスクの postExecute は、実行中のタスクがもうないかどうかを確認し、そうであれば更新ボタンを表示し、停止ボタンを非表示にします。

停止がクリックされた場合: すべてのタスクがキャンセルされ、更新ボタンが表示され、停止ボタンが非表示になります。

このコードは問題なく動作しますが、例外が 1 つあります。タスクの実行中に画面の向きを変更してアクティビティを再作成する場合です。ボタンは xml で定義された状態に戻ります (refresh=visibil、stop=gone)。

静的変数を使用して可視性の現在の状態を追跡すると、状況が悪化するだけです。これは、可視性を元に戻す必要がある実行中のタスクは、その時点で停止または破棄されている呼び出し元のアクティビティのビューしか変更できないためです。

public class MainActivity extends Activity
{
    private static List<MyAsyncTask> activeTasks = new LinkedList<MyAsyncTask>();

    private View refresh;
    private View stop;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.activity_main);
        this.refresh = findViewById(R.id.refresh);
        this.refresh.setOnClickListener(new OnClickListener()
        {
            public void onClick(View v)
            {   // Start a couple tasks
                new MyAsyncTask(MainActivity.this).execute();
                new MyAsyncTask(MainActivity.this).execute();
            }
        });
        this.stop = findViewById(R.id.stop);
        this.stop.setOnClickListener(new OnClickListener()
        {
            public void onClick(View v)
            { // Cancel all tasks and toggle refresh button
                cancelAll();
                MainActivity.this.enableRefresh(true);
            }
        });
    }

    public void enableRefresh(boolean enable)
    {
        if (this.refresh != null && this.stop != null)
        {
            this.refresh.setVisibility(enable ? View.VISIBLE : View.GONE);
            this.stop.setVisibility(!enable ? View.VISIBLE : View.GONE);
        }
    }

    public static void cancelAll()
    {
        for (MyAsyncTask task : MainActivity.activeTasks)
            task.cancel(true);
        MainActivity.activeTasks = new LinkedList<MyAsyncTask>();
    }

    private class MyAsyncTask extends AsyncTask<Void,Void,Void>
    {
        private MainActivity activity;

        public MyAsyncTask(MainActivity activity)
        {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute()
        {
            MainActivity.activeTasks.add(this);
            this.activity.enableRefresh(false);
        }

        @Override
        protected Void doInBackground(Void... v)
        {
            try
            { // Simulate a task
                Thread.sleep(3000);
            }
            catch (InterruptedException e)
            {
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void v)
        {
            MainActivity.activeTasks.remove(this);
            if (MainActivity.activeTasks.size() == 0)
                this.activity.enableRefresh(true);
        }
    }

}
4

3 に答える 3

1

http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

これを参照してください...向きの変更で状態を処理するのに役立ちます

于 2013-11-04T12:09:37.790 に答える
0

Tony Stark によるこのリンクhttp://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.htmlがおそらく最良の解決策だと思います。これにより、さらに多くの問題が解決される可能性があるからです。

ただし、目前の問題に対するより簡単な解決策を思いついたと思います。

MainActivity に静的変数を追加します。

private static MainActivity current;
private static boolean enableRefresh = true;

enableRefresh() の入力値を保存します。

public static void enableRefresh(boolean enableRefresh)
{
    MainActivity.enableRefresh = enableRefresh;
    (...) // Same as before
}

MainActivity onCreate() に追加:

MainActivity.current = this;
enableRefresh(enableRefresh);

AsyncTask では、コンストラクターで提供されるアクティビティの代わりに、更新するアクティビティとして MainActivity.current を使用します。

于 2013-11-05T00:21:17.433 に答える