好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

AsyncTask Missteps

AsyncTask Missteps

What's the Problem?

QA raise an incident, through the stack trace I know it's Dialog.show() called after Activity being destoryed. Specific to the code, we new a LoginTask in LoginActivity, if failed, we will show a dialog in onPostExecute(), crash happens when the Activity is destoryed but we still call the dialog.show() function.

So I solve this incident by surround the dialog.show() with an if block:

 1   if (! isFinishing()) {
  2       dialog.show();
  3  }

Everything seems to be fine, problem solved and minimum code changed. But ** point out two issues after review the submission:

1.. "If isFinishing is true, we probably don’t want to do any UI work." Except for dialog.show(), we also do many other UI work in onPostExcute().

2.. There may be same issue in other activities where an AsyncTask is used.

For the first question, indeed, the UI work is useless if Activity isFinishing, but as it also do no harm, so we can let them go. But for the second question, I do find a similar question in  AccountSignupActivity.java   , in SignupTask's onPostExecute() we also call dialog.show().

So the question is, how to use AsyncTask properly?

Is AsyncTask Really Entirely Flawed?

There is an interesting question in  StackOverflow   which pinpoint the problem:

1.. AsyncTask "allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.";

2.. But when we call dialog.show() in onPostExecute() it may cause a crash.

3.. Solve this problem we can use a Handler.

4.. But AsyncTask's role is to help us get rid of handler.

There are many answers under this question, but I'm not satisfied or not understood until I found this  blog   .

AsyncTask Missteps

This blog( http://www.shanekirk.com/2012/04/asynctask?missteps/  ) is really worth reading, it draws the problems and the solutions step by step. I'll quote the "One For All" solution here, but firstly let's summarize the problem:

1.. Dialog.show() crash happens when we reference a destroyed Activity, so maybe we can't reference the Activity in AsyncTask;

2.. But if we can't reference to an Activity, how can we update the UI?

3.. What will happen if the Activity destroyed but re?create again? Further more, what will happen if the AsyncTask is running or after the AsyncTask has completed?

4.. There is concurrent  AsyncTask limitations   .

Here goes the solution:

  1   public   class  MyActivity  extends   Activity
   2   {
   3       @Override
   4       public   void   onCreate(Bundle savedInstanceState)
   5       {
   6           super  .onCreate(savedInstanceState);
   7           setContentView(R.layout.main);
   8   
  9           //   Find views and assign them to member variables. 
 10   
 11          m_task =  (MyTask) getLastNonConfigurationInstance();
  12           if  (m_task !=  null  )
  13           {
  14              m_task.m_activity =  this  ;
  15               if   (m_task.m_isFinished)
  16                   m_task.updateUI();
  17           }
  18           else 
 19           {
  20              m_task =  new   MyTask();
  21              m_task.m_activity =  this  ;
  22               m_task.execute();
  23           }
  24       }
  25   
 26       @Override
  27       public   void   onDestroy()
  28       {
  29           super  .onDestroy();
  30   
 31          m_task.m_activity =  null  ;
  32   
 33           if  ( this  .isFinishing())
  34              m_task.cancel( false  );
  35       }
  36   
 37       @Override
  38       public   Object onRetainNonConfigurationInstance()
  39       {
  40           return   m_task;
  41       }
  42   
 43   
 44       static   class  MyTask  extends  AsyncTask<Void, Void, String>
 45       {
  46           @Override
  47           protected   String doInBackground(Void... params)
  48           {
  49               //   Do some long running task. We need to make sure
  50               //   we peridically check the return value of isCancelled(). 
 51               return   result;
  52           }
  53   
 54           @Override
  55           protected   void   onPostExecute(String result)
  56           {
  57              m_result =  result;
  58              m_isFinished =  true  ;
  59               updateUI();
  60           }
  61   
 62           public   void   updateUI()
  63           {
  64               if  (m_activity !=  null  )
  65               {
  66                   //   Update UI using m_result 
 67               }           
  68           }
  69   
 70           //   These should never be accessed from within doInBackground() 
 71          MyActivity m_activity =  null  ;
  72           boolean  m_isFinished  =  false  ;
  73          String m_result =  null  ;
  74       }
  75   
 76       private  MyTask m_task =  null  ;
  77   
 78       //   Various View member variables. 
 79  
 80  }

The problem solved by:

1.. Remove the implicit pointer by make the AsyncTask static

2.. Give an explicit Activity reference back to AsyncTask to direct control their relationships.

3.. Use a so called "connect/disconnect" pattern to handle the destroyed then re?create problem.

4.. Cancel the AsyncTask in onDestory().

Keep in Mind

Maybe there is no "One For All" solution, but there is one thing we must keep in mind: Never ever call dialog.show() or that kind of function without a check.
 I still don't know the full function list that will cause a crash except for dialog.show(), maybe we need not do any UI work if the Activity isFinishing, as **suggested.

Reference

? Incident:  https://engtools.engba.symantec.com/Etrack/readonly_inc.php?incident=3028953

? AsyncTask:  https://developer.android.com/reference/android/os/AsyncTask.html

? Is AsyncTask really conceptually flawed or am I just missing something?:  http://stackoverflow.com/q/3357477/1203241

? Android AsyncTask threads limits?:  http://stackoverflow.com/a/9654445/1203241

? AsyncTask Missteps:  http://www.shanekirk.com/2012/04/asynctask?missteps/

? Proper use of AsyncTask:  https://blogactivity.wordpress.com/2011/09/01/proper?use?of?asynctask/

 

 

分类:  Android

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于AsyncTask Missteps的详细内容...

  阅读:53次