【问题标题】:Updating Views through AsyncTasks通过 AsyncTasks 更新视图
【发布时间】:2013-11-04 12:04:27
【问题描述】:

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

此代码执行以下操作:

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

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

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

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

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);
        }
    }

}

【问题讨论】:

    标签: android android-asynctask android-activity


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      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();
          }
      

      希望有帮助

      【讨论】:

      • 如果我理解正确,这会在重新创建活动时尝试取消并重新运行任务。这似乎不对。
      【解决方案3】:

      我认为 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 作为要更新的活动,而不是构造函数中提供的活动。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-14
        • 2014-07-22
        相关资源
        最近更新 更多