通过AsyncTasks更新视图

时间:2013-11-04 12:04:27

标签: android android-asynctask android-activity

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

此代码执行以下操作:

单击

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

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

此代码工作正常,但有一个例外:当我通过更改屏幕方向在任​​务运行时重新创建活动时。按钮现在将返回到xml中定义的状态(refresh = visibile,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);
        }
    }

}

3 个答案:

答案 0 :(得分:1)

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

看到这一点,它将帮助你...处理方向变化中的状态

答案 1 :(得分: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); 
}
}

on savedInstanceState

添加

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

希望这个帮助

答案 2 :(得分: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作为要更新的活动,而不是构造函数中提供的活动。