0

下面是具有 2 个按钮的 Android Activity 的工作示例代码,其中只有 1 个是可见的:一个刷新按钮和一个停止按钮。

此代码执行以下操作:

单击刷新:启动一些 AsyncTasks。任务的 preExecute 将隐藏刷新按钮并显示停止按钮。任务的 postExecute 将检查是否没有更多正在运行的任务,如果是,则显示刷新按钮并隐藏停止按钮。

单击停止:取消所有任务,显示刷新按钮,隐藏停止按钮。

此代码工作正常,但有一个例外:当我通过更改屏幕方向运行任务时重新创建活动时。按钮现在将返回到 xml 中定义的状态(刷新=可见,停止=消失)。

使用静态变量来跟踪可见性的当前状态只会使情况变得更糟,因为必须将其切换回来的正在运行的 Task 只能修改调用活动中的视图,而此时已停止或销毁!

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 回答
0

要在屏幕方向上处理 AsyncTasks,请遵循此示例

MyAsyncTask myasynce;

    @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)
            {   
                //Register new Task
                myasynce = ( MyAsyncTask ) 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);
            }
        });
    }

现在onSaveInstanceState添加

@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);

//put myasynce status true if still runing false if finished          
outState.putBoolean("myasynce", ( myasynce != null && query.getStatus() != AsyncTask.Status.FINISHED ) ? true : false );
 if ( myasynce != null )
{
  myasynce.cancel(true); 
}
}

savedInstanceState

添加

    if ( savedInstanceState.getBoolean("myasynce") == true )
    {
//if task was running before screen orientation run it again
       myasynce = ( MyAsyncTask ) new MyAsyncTask(MainActivity.this).execute();
    }

希望这有帮助

于 2013-11-04T12:17:39.057 回答